@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
 
 
    }
 
}
posted @ 2021-04-19 11:09  小匠人  阅读(663)  评论(0编辑  收藏  举报