背景
bean在创建过程中会出现各种各样的循环依赖。了解spring如何用三级缓存机制解决循环依赖,解决spring没有解决的循环依赖。所以需要了解bean的生命周期原理。
出现属性的循环依赖时,bean的生命周期
spring用三级缓存机制来解决属性的循环依赖。
以 UserService 和 OrderService 出现属性的循环依赖为例子。
示例代码
@Component
public class OrderService {
@Autowired
UserService userService;
}
@Component
public class UserService {
@Autowired
OrderService orderService;
}
orderService 添加入set集合
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
singletonsCurrentlyInCreation 存储正在创建的 beanName ,后面用来检查是否出现了循环依赖。
这里把 "orderService" 添加进这集合。
创建bean的普通对象
createBeanInstance 中推断构造函数,然后实例化bean并返回
instanceWrapper = createBeanInstance(beanName, mbd, args);
将 orderService 添加到三级缓存中
三级缓存 singletonFactories 存储的是一个lambda 表达式。这个表达式用来存储 生成 orderService 对象的过程。后面出现循环依赖的时候会用到
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
orderService 属性填充
populateBean 会给 orderService 做属性填充,把 UserService 填充进去。在这里,会进入 UserService 的生命周期。
populateBean(beanName, mbd, instanceWrapper);
三级缓存中生成 orderService
UserService 的生命周期的步骤同上 orderService 的生命周期。
这里直接看到给 UserService 的bean生命周期中,对 字段 orderService 的属性注入过程。
这里需要把 orderService 从三级缓存中获取出来,然后放入二级缓存,如果需要AOP 这里会提前进行 AOP。
(注:这里二级缓存是为了,防止 UserService 出现多个循环依赖时,不生成多个代理对象。而存在,这里就不放开解释了。)
...
// 从 三级缓存 singletonFactories 里面找
// 获取到 lambda 表达式
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 执行 lambda 表达式
singletonObject = singletonFactory.getObject();
// 把结果放到 二级缓存 earlySingletonObjects 里面
this.earlySingletonObjects.put(beanName, singletonObject);
...
这里从三级缓存中获取到 orderService 并完成 UserService 的生命周期。
orderService 的AOP阶段
这里如果循环依赖提前进行了AOP 就不会再进行AOP获取代理对象了。
earlyProxyReferences 缓存的就是 执行lambda 表达式获取的 bean
private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);
orderService 放入单例池
因为出现了循环依赖所以从二级缓存中获取bean,放入单例池
把 orderService 从 set集合中删除
orderService 的生命周期结束,已经不是正在创建的 bean。所以这里把 orderService 从 set集合中 remove。
构造方法的循环依赖解决
构造方法的循环依赖,spring的三级缓存机制是解决不了的
因为卡在了创建普通对象,构造方法执行不了,普通对象都创建不成功
@Component
public class DemoAService {
public DemoAService(DemoBService demoBService) {
}
}
@Component
public class DemoBService {
public DemoBService(DemoAService demoAService) {
}
}
但是 加上 @Lazy 注解可以解决
@Lazy 不真正创建对象,返回一个代理对象。用的时候才会创建对象。
普通对象创建不成功,不影响
这里加上一个 @Lazy 就能解决
@Component
public class DemoAService {
@Lazy
public DemoAService(DemoBService demoBService) {
}
}
@Component
public class DemoBService {
public DemoBService(DemoAService demoAService) {
}
}
async 注解的循环依赖
同上。
给属性加上 @Lazy 之后,不存在循环依赖了。
加上 @Lazy 创建代理对象,执行的时候才会真正的创建对象。
标签:生命周期,依赖,spring,bean,缓存,orderService,UserService,public From: https://www.cnblogs.com/xiaosiyuan88888888/p/17303747.html