因为我英文水平有限(方法名记不住),所以本博客不会出现的具体方法名,有兴趣的好兄弟可以自己看看其他博客的回答。
首先什么是循环依赖?
通俗的来说就是我依赖你,你也依赖我,或者是我自己依赖自己,写成代码就是:
@Component
public class A {
@Autowired
private B b;
}
@Component
public class B {
@Autowired
private A a;
}
或者
@Component
public class A {
@Autowired
private A a;
}
spring在创建bean的时候有三步,实例化,属性注入,初始化,A在属性注入时需要B,但是B又需要注入A,这就是循环依赖,那这个问题怎么解决呢?
首先直接简单的来说spring主要是通过提前暴露bean来解决循环依赖的。
spring创建bean的过程有三步:实例化——属性注入——初始化,创建一个bean首先会去缓存中查询,如果缓存中没有该bean,就会进行创建,这里就要说一下spring的缓存了,spring的缓存分三级,分别存放创建好的单例bean(一级),已完成实例化未进行属性注入的bean(二级),提前暴露的一个单例工厂(三级,二级缓存中存储的就是从这个工厂里获得的对象),a和b循环依赖,首先查询缓存,a从未被创建过,所以直接走重载方法进行创建,先进行实例化,然后再进行属性注入之前在完成Bean的实例化后,属性注入之前Spring将Bean包装成一个工厂添加进了三级缓存中(注意这个单例工厂,非常重要),然后进行属性注入,发现a依赖b,那么这个时候需要去创建b,那么b也是实例化-属性注入-初始化这三个步骤,但是与a不同,b在属性注入的时候需要a是没错,但是a在实例化的时候将一个单例工厂添加到了三级缓存中,此时b可以通过这个单例工厂获得一个还没有初始化的a,这样就可以完成b的创建。
你是不是想问用没有初始化的a会不会有问题,答案是不会,因为虽然在创建B时会提前给B注入了一个还未初始化的A对象,但是在创建A的流程中一直使用的是注入到B中的A对象的引用,之后会根据这个引用对A进行初始化,所以这是没有问题的。