属性注入时,spring如何解决循环依赖()
提前声明:本文是基于spring.5.0.7.RELEASE
测试用例如下:
@Service("transactionServiceTest")
public class TransactionServiceTest implements TransactionService {@Autowired
private UserManager2 userManager2;
}@Component
public class UserManager2 {@Autowired
private TransactionServiceTest transactionServiceTest;
}
文章图片
图1
文章图片
图2
文章图片
图3
上面的图1、图2、图3分别表示项目启动后我们的测试类的创建顺序:
1.先创建TransactionServiceTest;
2.因为TransactionServiceTest依赖UserManager2,所以紧接着去创建UserManager2;
文章图片
图4
图4的红色方框的栈线程信息,反映的是spring注入TransactionServiceTest类里面的UserManager2属性;
文章图片
图5
图5反映的是spring创建UserManager2过程中发现其需要依赖TransactionServiceTest,而注入TransactionServiceTest属性的过程;最终调用了
DefaultSingletonBeanRegistry.getSingleton(beanName);
public Object getSingleton(String beanName) {
//注意这里的allowEarlyReference 值 是ture
return getSingleton(beanName, true);
}
下面是getSingleton()具体逻辑:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//因为此时TransactionServiceTest并没有完成初始化,因此 singletonObject = null;
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//最终在获取TransactionServiceTest对应的lamda表达式
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//这里执行lamda表达式,获取singletonObject实例
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
//lambda表达式删掉
this.singletonFactories.remove(beanName);
}
}
}
}
//最终返回singletonObject实例
return singletonObject;
}
lambda表达式的逻辑如下:
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
//调用AutowiredAnnotationBeanPostProcessor.getEarlyBeanReference方法;
//如果此时有必要被代理,也会在这里调用相应的后置处理器生成代理对象
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
【属性注入时,spring如何解决循环依赖()】lambda表达式执行完成之后,生成一个早期对象,为什么叫早期对象呢?因为此时的bean对象还没有被执行初始化逻辑;
接下来,UserManager2执行初始化逻辑,初始化完成后,TransactionServiceTest接着进行初始化。至此,循环依赖处理完成。
推荐阅读
- 投稿|天价索赔、恶意抢注,出海“版权坑”有多深?
- JAVA|初步认识JAVA
- 文旅产业研究|脱离金融属性的数字藏品,价值何在?
- 投稿|恢复注册后,满帮还有更多挑战
- 如何利用python读取图片属性信息
- 机器学习和深度学习|tensorflow的安装(要注意版本哦)
- YAYA LIVE CTO 唐鸿斌(真正本地化,要让产品没有「产地」属性)
- 计算机|全新升级的AOP框架Dora.Interception[5]: 实现任意的拦截器注册方式
- 六|6.1_1 Python3.x入门 P1 【基础】基础语法、注释、标识符、变量、数据类型、键盘录入input
- Spring|Spring Cloud Alibaba(02)——Nacos服务注册和配置中心