@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類來測試
@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 } }

底層源碼:
跟到后面可以看到創建了cglib動態代理: