@Lazy解决循环调用问题
@Service
public class A extends GenericBaseService {
@Autowired
private B b;
}
@Service
public class B extends GenericBaseService {
@Autowired
private A a;
}
spring中的bean和java对象的区别:
假如有个类Student,对于java对象 Student st=new Student();
但对于bean: 创建出java对象后还要经过一系列的处理器处理,如是否需要动态代理,是否需要注入各种属性
spring底层是支持循环依赖的,A依赖B B依赖A,这里说的A和B都是spring bean;
如果把bean的创建过程简述为2个步骤的话: 1. 创建 一个对象(底层通过反射) 2. 给对象注入属性,那么A和B的创建流程如下
1. A的创建: A a=new A();
2. 属性注入:发现需要B
3. 创建B b=new B();
4. 属性注入: 发现需要A,此时A已经创建了.只是还没经过各种后置处理器处理,所以B是可以完成属性注入的,只是一个半成品
5.之后回到第2步,就可以给A赋值了,循环依赖到此解决
//然而生产中的情况复杂多,相互依赖的关系网太复杂了,所以经常还是会出现提示循环依赖的异常,此时可以用另外一个方式去解决,那就是@Lazy注解了
@Service
public class A extends GenericBaseService {
@Autowired
@Lazy
private B b;
}
加了lazy的原理如下:
1. A的创建: A a=new A();
2. 属性注入:发现需要B,查询字段b的所有注解,发现有@lazy注解,那么就不直接创建B了,而是使用动态代理创建一个代理类B
3. 此时A跟B就不是相互依赖了,变成了A依赖一个代理类B1,B依赖A
验证这个方式很简单:
从容器中分别获取A a 和B b 的实例对象,然后从A中获取它依赖的对象b1,打印b1的class对象,判断b1是否和b相等
//下面使用Student和School类来测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
@Component public class School { @Autowired @Lazy private Student student; public Student getStudent() { return student; } public void setStudent(Student student) { this .student = student; } } @Component public class Student { @Autowired private School school; public School getSchool() { return school; } public void setSchool(School school) { this .school = school; } } public class APP { public static void main(String[] args) throws InterruptedException { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Configurate. class ); School school =(School) applicationContext.getBean( "school" ); Student student =(Student) applicationContext.getBean( "student" ); System.out.println(school.getClass()); //class com.aop.School System.out.println(student.getClass()); //class com.aop.Student System.out.println(school.getStudent()==student); //false System.out.println(school.getStudent().getClass()); //class com.aop.Student$$EnhancerBySpringCGLIB$$834812b7 } } |