JavaEE图书管理项目
1.String对象的比较:
1.==比较是否进行引用同一个对象
对于我们简单类型或者内置类型来说,我们直接比较的是变量的值,对于引用类型,我们比较的是引用中的地址,也就是说,对于我们的基本变量类型来说,==比较的是引用的地址
package CompileRun; public class HelloWorld { public static void main(String[] args) { int a=10; int b=20; int c=30; //对于我们的基本变量来说,==比较的是两个变量中存储的值是否相同 System.out.println(a==b);//false System.out.println(a==c);//false //对于我们的引用类型来说,==比较的是两个引用变量是否指向的是同一个变量 String str1=new String("hello"); String str2=new String("hello"); String str3=new String("world"); String str4=str3; System.out.println(str1==str2);//false System.out.println(str2==str3);//false System.out.println(str3==str4); } }
2.boolean equals(Object anObject)
1)我们的String类是重写了Object中的equals()方法,Object中的equals默认使用==来进行比较,String重写equals方法之后,按照如下规则来进行比较:
2)对象运算符(instanceof)用来判断一个对象是否属于某个指定的类或其子类的实例,如果是,返回真(true),否则返回假(false)
public boolean equals(Object anObject) { if (this == anObject) { //1.我们先进行比较this和anObject是否是同一个对象进行比较,如果它们是同一个对象,那么就直接返回true return true; } if (anObject instanceof String) { //2.进行检测anObject是否是String类型的对象,如果是我们就继续进行比较,不是就进行返回 //3.将anObject进行向下转型成为String类型的对象(向下转型:父类引用的对象转换为子类类型称为向下转型) String anotherString = (String)anObject; int n = value.length; //4.我们来进行比较一下this和anObject两个字符串的长度是否相同,如果相同,那么就继续进行比较,否则就会返回false if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; //5.从前向后,逐个字符进行比较 while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
3.重写hashCode方法:
1)我们的hashcode方法,我们的这个方法用于确定对象在内存中存储的位置是否相同,在我们的散列表中hashcode()的作用是进行获取到对象的散列码,从而我们来进行确定该对象在散列表中的位置
2)我们来看下面的代码,没有进行重写hashcode方法,但是我们的两个对象具有相同的内容,但是我们所得出的hashcode的值是不相同的
class Person { public String name; public int age; public Person(String name, int age) { this.name = name; this.age = age; } } public class TestDemo4 { public static void main(String[] args) { Person per1 = new Person("xin", 21) ; Person per2 = new Person("xin", 21) ; System.out.println(per1.hashCode()); System.out.println(per2.hashCode()); } }
所以,我们如果希望说如果两个对象有者相同的内容,那么我们说在内存的位置应该是相等的,我们就需要进行重写hashcode方法
1.对于AOP的理解:
是对之前面向对象的一种补充,拦截器是AOP的一种实现,我们的拦截器会做一个参数校验,只有登陆了才可以请求通过,但是我们的AOP,我们只是定义一个切面,当我们执行环绕通知的时候,也会拦截,但不会做任何的参数校验
比如说当我们实现了一个单例类的时候,我们的外部人员还是new了一个类怎们办?
当我们的构造方法是私有的时候,在外部是不能够进行new的
AOP是一种思想,但是拦截器是Spring自身的规则,也是AOP思想的一个实现,拦截器是拦截当前项目的所有接口,但是当引入AOP之后,就可以进行指定我们所拦截的一个规则了
使用AOP的方法:
1)在项目里面添加依赖:引入AOP框架
2)添加一个切面:AOP实现的是更小维度的一个拦截,使用@Aspect注解,表明这个类是作为我们的AOP来进行拦截使用的
3)写一个空方法,实现一个切点,指明拦截的规则,使用@pointcut注解,指明我们的拦截规则(拦截哪些类),一个切点可以有被很多通知实现,切点可以有一个或者多个;
4)添加通知,在我们的通知里面指明这个通知是属于哪一个切点的(在对应的注解里面指明),指定切点的名字就是使用@pointcut修饰的方法
注意我们在实现环绕通知的时候,必须要进行传递参数,就是ProceedingJoinPoint joinPoint参数,这个类是用来执行我们的UserController里面的方法的,我们可以使用joinPoint中的proceed方法来执行我们的Controller里面的代码,我们就可以在这个方法实现之前和实现之后来干我们想要干的事情了
比如说我们实现事务的一个开启和提交,我们在proceed方法执行之前开启一个事务,在proceed方法执行完之后提交一个事务,在我们的catch语句块里面回滚一个事务
2.Spring的事务传播机制:
我们要想使用Spring的事务传播机制,那么我们先干两件事情:
1.引入依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
2.我们要写上MYSQL的配置文件(如果不写就会发生异常):
logging.level.root=warn #数据库连接配置: spring.datasource.url=jdbc:mysql://127.0.0.1:3306/javaee?characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=12503487 spring.datasource.driver-class-name=com.mysql.jdbc.Driver
@Controller public class BlogController { @RequestMapping("/Java100") @ResponseBody public String start() { GetAll(); return "生命在于运动"; } public void GetAll() { TestA(); TestB(); } public void TestA() { System.out.println(1); } @Transactional(propagation=Propagation.MANDATORY) public void TestB() { System.out.println(2); } }
我们的上面的这种写法是错误的,对我与我们的事务开启,自己调用自己的方法是不会触发到AOP的,还不能用static关键字来进行修饰的
举个例子:Propagation.REQUIRED:是一个默认的隔离级别,它表示如果当前存在事务,那么就直接加入到事务里面,如果当前没有事务,就进行创建一个新的事务
写一段代码:当前我们会把两个get方法都会加到一个事务里面
1)我们的User1Controller1里面的代码: package com.example.demo; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; @Controller public class User1Controller { @Transactional public String get() { return "我叫"; } } 2)咱们的User2Controller2里面的代码: package com.example.demo; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; @Controller public class User2Controller { @Transactional public String get() { return "李佳伟"; } } //3咱们的UserController里面的代码: package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class UserController { @Autowired User1Controller user1Controller; @Autowired User2Controller user2Controller; @RequestMapping("/Java100") @ResponseBody public String GetAll() { return user1Controller.get()+user2Controller.get(); } }
1)就拿我们的Propagation.REQUIRED来说,当我们的GetAll()方法没有加上@Transactional注解,这时候只要GetAll里面中调用的方法有一个加了@Transactional,那么就会把这个方法连同调用它的方法当成一个事务
2)拿我们的Propagation.SUPPORTS,如果说当我们的GetAll()方法没有加上@Transactional注解,那么就算我们的两个方法加上了Propagagation.SUPPORTS,那么我们的方法也会以非事务形态来进行运行,况且来说,如果说我们的GetAll方法加上了事务,况且两个方法都加上了@Transactional(propagation = Propagation.SUPPORTS),那么我们的两个方法加上主方法都会当成一个事务来进行,只要有一个步骤出错,那么整个过程就会及进行回滚;