
@Component
public class A {
@Autowired
private B b;
}
@Component
public class B {
@Autowired
private A a;
}
依赖情况 | 依赖注入方式 | 循环依赖是否被解决 |
|---|---|---|
AB相互依赖(循环依赖) | 均采用setter方法注入 | 是 |
AB相互依赖(循环依赖) | 均采用构造器注入 | 否 |
AB相互依赖(循环依赖) | A中注入B的方式为setter方法,B中注入A的方式为构造器 | 是 |
AB相互依赖(循环依赖) | B中注入A的方式为setter方法,A中注入B的方式为构造器 | 否 |
Spring在创建Bean的过程中分为三步
AOP代理以上面AB相互依赖为例
@Component
public class A {
@Autowired
private B b;
}
@Component
public class B {
@Autowired
private A a;
}getBean方法,这个方法有两层含义 getSingleton(a)方法,这个方法又会调用getSingleton(beanName, true)允许提前曝光引用public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}singletonObjects,一级缓存,存储的是所有创建好了的单例BeanearlySingletonObjects,完成实例化,但是还未进行属性注入及初始化的对象singletonFactories,提前暴露的一个单例工厂,二级缓存中存储的就是从这个工厂中获取到的对象
getSingleton(beanName, singletonFactory)createBean方法返回的Bean最终被放到了一级缓存,也就是单例池中public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// ....
// 省略异常处理及日志
// ....
// 在单例对象创建前先做一个标记
// 将beanName放入到singletonsCurrentlyInCreation这个集合中
// 标志着这个单例Bean正在创建
// 如果同一个单例Bean多次被创建,这里会抛出异常
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// ....
// 用于记录异常相关信息
// ....
try {
// 上游传入的lambda在这里会被执行,调用createBean方法创建一个Bean后返回
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
// ...
// 省略catch异常处理
// ...
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 创建完成后将对应的beanName从singletonsCurrentlyInCreation移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加到一级缓存singletonObjects中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
creatBean中的核心内容
在完成Bean的实例化后,属性注入之前Spring将Bean包装成一个工厂对象添加进了三级缓存中,对应源码如下:

ObjectFactory)的getObject方法可以得到一个bean对象getEarlyBeanReference这个方法创建的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;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}getEarlyBeanReferenceAOP的情况下,上面的代码等价于:protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
return exposedObject;
}根据流程图串一下流程:

A依赖B,B依赖A,自然排序,所以先实例化A
AOP相关,我们再来看一看getEarlyBeanReference的代码: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;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}开启AOP的情况下,那么就是调用到AnnotationAwareAspectJAutoProxyCreator的getEarlyBeanReference方法public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
// 如果需要代理,返回一个代理对象,不需要代理,直接返回当前传入的这个bean对象
return wrapIfNecessary(bean, beanName, cacheKey);
}AOP代理的话代理对象而不是A的实例化阶段创建后的对象
1、在给B注入的时候为什么要注入一个代理对象?
AOP代理时2、明明初始化的时候是A对象,那么Spring是在哪里将代理对象放入到容器中的呢?
代理对象工厂放入三级缓存populateBean()属性填充时候去创建B代理对象,并放入二级缓存,并删除三级缓存原始对象
3、初始化的时候是对A对象本身进行初始化,而容器中以及注入到B中的都是代理对象,这样不会有问题吗?
目标类的引用4、三级缓存为什么要使用工厂而不是直接使用引用?换而言之,为什么需要这个三级缓存,直接通过二级缓存暴露一个引用不行吗?
延迟对实例化阶段生成的对象的代理我们思考一种简单的情况,就以单独创建A为例,假设AB之间现在没有依赖关系,但是A被代理了,这个时候当A完成实例化后还是会进入下面这段代码:
// A是单例的,mbd.isSingleton()条件满足
// allowCircularReferences:这个变量代表是否允许循环依赖,默认是开启的,条件也满足
// isSingletonCurrentlyInCreation:正在在创建A,也满足
// 所以earlySingletonExposure=true
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
// 还是会进入到这段代码中
if (earlySingletonExposure) {
// 还是会通过三级缓存提前暴露一个工厂对象
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}循环依赖,那没有办法,只有给Bean先创建代理最后一步完成代理而不是在实例化后就立马完成代理没有循环依赖,只是三级缓存添加了一个代理A对象工厂(不会执行),A对象会在初始化最后一步生成代理对象,然后放入一级缓存,最后清空二三级缓存Spring是如何解决的循环依赖?
singletonObjects),二级缓存为早期曝光对象(earlySingletonObjects),三级缓存为早期曝光对象工厂(singletonFactories)AOP代理,那么通过这个工厂获取到的就是A代理后的对象没有被AOP代理,那么这个工厂获取到的就是A实例化的对象对象工厂getObject方法来获取到对应的对象,得到这个对象后将其注入到B中为什么要使用三级缓存呢?二级缓存能解决循环依赖吗?
实例化后就要完成AOP代理,这样违背了Spring设计的原则