循环依赖三重境界之二:@EnableAspectJAutoProxy

1,131 阅读3分钟

循环依赖三重境界之一:简单循环依赖
juejin.cn/post/684490…

循环依赖三重境界之二:@EnableAspectJAutoProxy
juejin.cn/post/684490…

循环依赖三重境界之三:@Async
juejin.cn/post/684490…

为什么会有这篇文章

网上循环依赖的文章数不胜数,代理的文章也数不胜数,但是循环依赖加上代理,就有点问题了,我想了一段时间才想通,所以记录下来。

先看看网上说的循环依赖:

  1. 获取单例A,A不存在
  2. 进行创建,放入缓存
  3. 注入依赖B
  4. 发现B不在,创建B
  5. 注入A,发现缓存中已经存在A,注入成功
  6. B初始化成功
  7. 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都要进行代理,想想会怎么样?

  1. 创建A,发现没有放入缓存
  2. 注入属性B
  3. 发现没有B,创建B
  4. 初始化B,注入A,发现缓存中有A,此时对A做代理,得到代理对象A1
  5. B中有了代理对象A1
  6. 对B做代理,得到代理对象B1,此时B1中有A1
  7. 对A做代理,得到代理对象A2

等等,A2中有B1,B1中有A1,这好像不是循环依赖啊,是不是漏了什么东西?

启个项目debug

在B中对A做的代理,拿到的是

然后对B做代理,拿到的是

再返回到A的初始化过程中 代理A之前

代理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注入

在populate之后,可以看到A的代理对象A1的target中已经有了B的代理对象B1,此时A1中有B1,B1中有A1,循环依赖+代理,大功告成。

总结流程

原图:www.processon.com/view/link/5…

补充:

今天跟朋友又聊到了这个问题,复习一下,顺便记录一下,非循环依赖模式下的代理是这样的

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

可以看到是有些不同的