概述
Bean 的加载涉及到 获取 Bean 定义,实例化、属性填充、初始化过程。
在初始化阶段 ,Spring 对 Aware、BeanPostProcessor 等扩展点进行了实现,对 Bean 进行增强。
在初始化阶段,有将 Bean 放到三级缓存,然后到二级缓存,最后初始化完成放到一级缓存的过程,具体可以看看上篇文章。
Spring Bean 加载过程生命周期源码分析
注意:
- Spring 只解决了单例 Bean 循环依赖的情况
-
样例代码
样例代码只包含 3 个类,启动类 SpringBeanCircleApplication ,CircularServiceA 依赖 CircularServiceB,CircularServiceB 依赖 CircularServiceA 。 ```java @SpringBootApplication public class SpringBeanCircleApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBeanCircleApplication.class, args);
} }
@Service public class CircularServiceA {
@Autowired
private CircularServiceB circularServiceB;
}
@Service public class CircularServiceB {
@Autowired
private CircularServiceA circularServiceA;
}
<a name="kw9qy"></a>
# 源码分析
循环依赖的 Bean 加载流程:
1. A 的**加载流程**包括**实例化、属性填充、初始化**三个阶段。A 实例化完成之后,会将 Bean 标记为**创建中**(还未属性填充、初始化)、并且实例的 objectFactory 加入到三级缓存。其中在 A **属性填充**阶段,发现 B 还未加载,进而去执行 B 的加载流程
1. B 的加载流程和 A 一样,B 实例化完成后,会将 B 标记为创建中、加入到三级缓存。此时三级缓存中有 A、B 的 ObjectFactory。
1. 在 B **属性填充**阶段,又发现 A ,进而**又去加载 A** 。加载 A 发现其正在**创建中**,并且三级缓存中有 A,那么将 A 放到二级缓存,并返回 A 的引用。
1. 至此 B 属性填充完成,再执行 B 初始化,初始化完成后将 B 从三级移动到二级再移动到一级缓存中。
1. 再执行 A 属性填充后的初始化流程,并放到一级缓存。最终,一级缓存里面包含 A 和 B 初始化完成的实例
沿用网上一张图片:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/210984/1653355734935-d0ffb50d-9851-4774-b6ad-38598e13dfbc.png#clientId=ue0214836-b5ff-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u811a7ea2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=972&originWidth=1257&originalType=url&ratio=1&rotation=0&showTitle=false&size=143634&status=done&style=none&taskId=ufd1cbcc5-dc7a-4ab5-af6d-eef2d44f213&title=)
<a name="bKUGI"></a>
## 1. getBean(A)
A 的加载流程
<a name="vIF5O"></a>
### 1.1 AbstractBeanFactory
- 从 getBean 开始,首先从缓存中获取(**这个步骤很重要**)
- 若缓存中没有,再获取 A 的定义,其次调用 getSingleton 去获取 A 的实例,createBean 方法用于创建 A 的 objectFactory。
- 若缓存中有,直接返回实例
```java
public abstract class AbstractBeanFactory {
public Object getBean(String name) throws BeansException {
return this.doGetBean(name, (Class)null, (Object[])null, false);
}
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
Object sharedInstance = this.getSingleton(beanName); // 从缓存中获取 A,第一次显然获取不到
try {
RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName); // 获取 Bean 定义
if (mbd.isSingleton()) {
// 获取 A 的实例
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args); // 执行 singletonFactory.getObject 会被调用
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
}
}
}
1.2 DefaultSingletonBeanRegistry
- getSingleton(String beanName, ObjectFactory<?> singletonFactory) 执行到 singletonFactory.getObject 这一行时,会调用函数调用的地方 Lamda 表达式的 AbstractAutowireCapableBeanFactory.createBean 方法
getSingleton 方法结束部分,表示 Bean 已经初始化完成,此时移除 Bean 创建中标记,并加入到一级缓存中
public class DefaultSingletonBeanRegistry {
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized(this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName); // 再次从缓存中获取 A,显然获取不到
if (singletonObject == null) {
this.beforeSingletonCreation(beanName); // 标记创建中,加入到 singletonsCurrentlyInCreation
try {
singletonObject = singletonFactory.getObject(); // 执行 lamda 表达式,AbstractAutowireCapableBeanFactory.createBean 返回 实例
newSingleton = true;
} finally {
// A 加载结束,移除正在创建标记 singletonsCurrentlyInCreation
this.afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加到一级缓存,删除二级缓存与一级缓存
this.addSingleton(beanName, singletonObject);
}
}
}
}
}
1.3 AbstractAutowireCapableBeanFactory
执行具体 Lamda 表达式的内容,注意属性填充前,将对象加入的三级缓存的部分,后面会说到三级缓存的作用 ```java public abstract class AbstractAutowireCapableBeanFactory { protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
}
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
if (instanceWrapper == null) {
instanceWrapper = this.createBeanInstance(beanName, mbd, args); // A 实例化
}
// 是否单例 && 运行循环依赖 && 创建中
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
// 将对象放到三级缓存
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
try {
this.populateBean(beanName, mbd, instanceWrapper); // 属性填充(此时发现 A )
exposedObject = this.initializeBean(beanName, exposedObject, mbd); // 初始化
}
if (earlySingletonExposure) {
// 只从一级缓存和二级缓存中取
Object earlySingletonReference = this.getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
}
}
} }
// 属性填充 protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (resolvedAutowireMode == 1 || resolvedAutowireMode == 2) { MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs); if (resolvedAutowireMode == 1) { this.autowireByName(beanName, mbd, bw, newPvs); }
if (resolvedAutowireMode == 2) {
this.autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
}
protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { for(int var8 = 0; var8 < var7; ++var8) { String propertyName = var6[var8]; if (this.containsBean(propertyName)) { // 如果含有 Bean,那么执行 Bean 加载逻辑 Object bean = this.getBean(propertyName); // A 发现 B,那么执行 B 的加载流程 } }
}
**可以发现,在 A 的 populateBean 阶段,会去调用 getBean(B) 的逻辑**
<a name="D7agh"></a>
## 2. getBean(B)
B 的加载流程,其加载流程和 A 一样(1.1,1.2,1.3 部分)<br />**重点来了,在 B 的 populateBean 阶段,又发现了 A,此时再去执行 getBean(A)**
<a name="umAd1"></a>
## 3. getBean(A)
A 再次被加载<br />AbstractBeanFactory.getBean 方法开头,发现此时**三级缓存**中有 A 的 ObjectFactory,并且标记为创建中,那么把 A 的 ObjectFactory **从三级缓存**(singletonFactories)**放到二级缓存**(earlySingletonObjects)中,并返回 A 的提前曝光实例(还未初始化完成)
```java
public abstract class AbstractBeanFactory {
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
Object sharedInstance = this.getSingleton(beanName);
if (sharedInstance != null && args == null) {
beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
}
}
public class DefaultSingletonBeanRegistry{
@Nullable
public Object getSingleton(String beanName) {
return this.getSingleton(beanName, true);
}
// 从缓存获取逻辑
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName); // 从一级缓存获取
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) { // 没有获取到并且正在创建中
singletonObject = this.earlySingletonObjects.get(beanName); // 从二级缓存获取
if (singletonObject == null && allowEarlyReference) { // 二级缓存也没有获取到,并且允许提前返回引用
synchronized(this.singletonObjects) { // 加锁
singletonObject = this.singletonObjects.get(beanName); // 再次从一级缓存获取
if (singletonObject == null) { // 一级没有
singletonObject = this.earlySingletonObjects.get(beanName); // 二级中获取
if (singletonObject == null) { // 二级也没有
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName); // 从三级获取
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject); // 从三级中获取到了,删除三级缓存,加入到二级缓存中
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
}
4. B 初始化完成
上一步 B 属性填充完成之后,执行 AbstractAutowireCapableBeanFactory 中后续的初始化流程、并在 DefaultSingletonBeanRegistry.getSingleton 方法最后,移除 Bean 创建中标记,将缓存从三级移到一级。
5. A 初始化完成
为什么需要三级缓存
根据上面流程可知,A、B 的加载,首先都会放到三级缓存中,当再次调用 getBean(A) 方法时,从三级缓存中通过 ObjectFactory.getObject 获取 A 的实例。
若 A 被 AOP 代理,那么执行匿名表达式的exposedObject = bp.getEarlyBeanReference(exposedObject, beanName)操作,返回的是 A 的代理对象
可以用反证法证明三级缓存的必要性:
- 若只有两级缓存,创建 A 实例时,不知道是否有循环依赖,先将 A 放到二级缓存;创建 B 实例时,也放入二级缓存。
- B 属性填充阶段发现了 A,进从二级缓存中找到了 A,若 A 被 AOP 代理,此时从二级缓存中获取的 A 是原始对象并不是代理对象,不符合要求。
- 若一开始将 A 的代理对象放入二级缓存,这样违背了 Spring AOP 与 Bean 的生命周期的设计,因为在没有循环依赖的常规情况下,AOP 的实现都是 Bean 初始化完成之后才进行。
所以若出现了循环依赖,三级缓存就很有必要,把实例对象的 ObjectFactory 放到三级缓存中,通过 singletonFactory.getObject() 方法判断是否需要返回 A 的代理类,对 A 提前做增强。
public abstract class AbstractAutowireCapableBeanFactory {
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
// 是否单例 && 运行循环依赖 && 创建中
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
// 将对象放到三级缓存
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
}
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
SmartInstantiationAwareBeanPostProcessor bp;
// 有代理
if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
// for 循环参数结尾,返回实例的提前曝光对象
for(Iterator var5 = this.getBeanPostProcessorCache().smartInstantiationAware.iterator(); var5.hasNext(); exposedObject = bp.getEarlyBeanReference(exposedObject, beanName)) {
bp = (SmartInstantiationAwareBeanPostProcessor)var5.next();
}
}
// 返回可能被代理的对象
return exposedObject;
}
}
循环依赖情况
| 依赖情况 | 依赖注入方式 | 循环依赖是否被解决 | | —- | —- | —- | | AB相互依赖(循环依赖) | 均采用 setter 方法注入 | 是 | | AB相互依赖(循环依赖) | A中注入B的方式为setter方法 | 是 | | AB相互依赖(循环依赖) | B中注入A的方式为 setter 方法,A中注入B的方式为构造器 | 否 | | AB相互依赖(循环依赖) | B中注入A的方式为setter方法,A中注入B的方式为构造器 | 是(可以使用 @Lazy 解决) |
- Spring 创建 Bean 是按照自然排序,若主 Bean 是 setter 方式,那么依赖 Bean 是 setter 注入或者构造器注入,都可以解决循环依赖问题
- 均使用构造器注入,可以使用 @Lazy 解决,其基本思路是:对于强依赖的对象,一开始并不注入对象本身,而是注入其代理对象
```java
@Service
public class CircularServiceA {
private CircularServiceB circularServiceB;
public CircularServiceA(@Lazy CircularServiceB circularServiceB){
} }this.circularServiceB = circularServiceB;
@Service public class CircularServiceB { private CircularServiceA circularServiceA; public CircularServiceB(CircularServiceA circularServiceA){ this.circularServiceA = circularServiceA; } } ```