循环依赖三重境界之一:简单循环依赖
juejin.cn/post/684490…
循环依赖三重境界之二:@EnableAspectJAutoProxy
juejin.cn/post/684490…
循环依赖三重境界之三:@Async
juejin.cn/post/684490…
为什么会有这篇文章
网上循环依赖的文章数不胜数,代理的文章也数不胜数,但是循环依赖加上代理,就有点问题了,我想了一段时间才想通,所以记录下来。
先看看网上说的循环依赖:
- 获取单例A,A不存在
- 进行创建,放入缓存
- 注入依赖B
- 发现B不在,创建B
- 注入A,发现缓存中已经存在A,注入成功
- B初始化成功
- A初始化成功
再看看代理:
代理是通过一个后置处理器AbstractAutoProxyCreator处理的,无非就是做了个动态代理
那么问题在哪儿?
我们仔细看下源码
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
**//这里放入缓存**
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
**//这里注入属性**
populateBean(beanName, mbd, instanceWrapper);
**//这里动态代理**
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
如果A和B都要进行代理,想想会怎么样?
- 创建A,发现没有放入缓存
- 注入属性B
- 发现没有B,创建B
- 初始化B,注入A,发现缓存中有A,此时对A做代理,得到代理对象A1
- B中有了代理对象A1
- 对B做代理,得到代理对象B1,此时B1中有A1
- 对A做代理,得到代理对象A2
等等,A2中有B1,B1中有A1,这好像不是循环依赖啊,是不是漏了什么东西?
启个项目debug
在B中对A做的代理,拿到的是




有问题,A居然没有被代理! 重新debug发现,在B拿到A的代理对象时,把A放入到了一个map中

在最外层的A初始化时,再进行代理,发现A已经代理过了,就不再对A进行代理了

我们继续往下看

可以发现,最终暴露出来的并不是在外层进行了一顿注入/后置处理操作的A,而是从缓存中拿到的A。(不代理时也是如此,不赘述了)
那么现在问题变成了: B从缓存中创建A的代理对象A1,注入,对B进行代理,这样,B中有了A1,可是A1好像没有依赖上B?
这个问题其实和代理有关,我们在产生代理对象A1的时候,将目标对象A的实例传进去,将B的代理对象B1注入A之后,产生的代理对象A1也有了B的代理对象B1。可以看看代码是怎么做的。
B从缓存中拿A,A的生产过程: 此时目标对象中还没有B,因为还没有populate注入



总结流程

原图:www.processon.com/view/link/5…
补充:
今天跟朋友又聊到了这个问题,复习一下,顺便记录一下,非循环依赖模式下的代理是这样的

A----B----A,B中代理A时的代理是这样的

可以看到是有些不同的