spring中bean的生命周期

发布时间 2023-04-10 17:55:56作者: 毛毛雨1997

背景

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" 添加进这集合。

gh

创建bean的普通对象

createBeanInstance 中推断构造函数,然后实例化bean并返回

instanceWrapper = createBeanInstance(beanName, mbd, args);

gh

将 orderService 添加到三级缓存中

三级缓存 singletonFactories 存储的是一个lambda 表达式。这个表达式用来存储 生成 orderService 对象的过程。后面出现循环依赖的时候会用到

private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

gh

orderService 属性填充

populateBean 会给 orderService 做属性填充,把 UserService 填充进去。在这里,会进入 UserService 的生命周期。

populateBean(beanName, mbd, instanceWrapper);

gh

三级缓存中生成 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);
...

gh

这里从三级缓存中获取到 orderService 并完成 UserService 的生命周期。

orderService 的AOP阶段

这里如果循环依赖提前进行了AOP 就不会再进行AOP获取代理对象了。

earlyProxyReferences 缓存的就是 执行lambda 表达式获取的 bean

private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);

gh

orderService 放入单例池

因为出现了循环依赖所以从二级缓存中获取bean,放入单例池

gh

把 orderService 从 set集合中删除

orderService 的生命周期结束,已经不是正在创建的 bean。所以这里把 orderService 从 set集合中 remove。

gh

构造方法的循环依赖解决

构造方法的循环依赖,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 创建代理对象,执行的时候才会真正的创建对象。