Spring解决循环依赖
什么是循环依赖?
在我们实际开发中,可能会碰到A业务的Service需要调用B业务Service中的某个方法,
并且B业务Service也要调用A.Service的某个方法,这样,就会形成循环依赖。
如下代码,就形成了AService和BService的循环依赖。
@Service
public class AService {
@Autowired
private BService bService;
}
@Service
public class BService {
@Autowired
private AService aService;
}
Spring中循环依赖的场景
- 构造器循环依赖。(未解决)
- 依赖注入Field字段的循环依赖。(已解决)
Spring解决循环依赖的思路
Bean创建过程
Bean的创建从整体上讲分为三个阶段
createBeanInstance() 拿到BeanWrapper对象,在创建过程中将半成品的Bean放入三级缓存(稍后再说缓存)
populateBean() 属性赋值
initializeBean() 初始化Bean实例
三级缓存
Bean的创建都是通过getBean()方法来实现的。
在DefaultSingletonBeanRegistry类中,我们可以看到几个Map缓存
/** Cache of singleton objects: bean name to bean instance. */
/** 一级缓存,缓存单例Bean,key为beanName, value是Bean实例 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
/** 二级缓存,缓存单例Bean工厂,key为beanName,value为bean工厂 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
/** 三级缓存,字面意思,缓存早期的bean */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/** Names of beans that are currently in creation. */
/** 正在创建的bean,比如果构造器初始化时,A初始化参数为B,调用A的构造器,但是B还未创建,就会先去创建B,此时A就属于正在创建 */
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
getSingleton()
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 先从一级缓存中获取单例对象
Object singletonObject = this.singletonObjects.get(beanName);
// 如果一级缓存中没有,并且当前的bean正在创建
// isSingletonCurrentlyInCreation(beanName)就是判断singletonsCurrentlyInCreation中有没有beanName
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 如果当前bean正在创建,就从二级缓存中获取
singletonObject = this.earlySingletonObjects.get(beanName);
// 如果二级缓存中还没有,并且允许从三级缓存中获取
if (singletonObject == null && allowEarlyReference) {
// 从三级缓存中获取Factory
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// 如果三级缓存中有,就把三级缓存中的对象移动到二级缓存中去,并移除三级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
getSingleton()方法的调用发生在createBeanInstance()之后,也就是此时单例bean对象已经创建好了,虽然没进行依赖注入和实例化,但是可以提前抛出来当做标记使用。
doCreateBean()
doCreateBean()是Bean创建的核心,包含了createBeanInstance(),populateBean(),initializeBean(),
以下只保留核心代码,详细的可以到AbstractAutowireCapableBeanFactory中看doCreateBean()方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// 创建BeanWrapper对象
BeanWrapper instanceWrapper = null;
if (instanceWrapper == null) {
// 给BeanWrapper对象赋值
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 添加三级缓存
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
try {
// 对象属性赋值
populateBean(beanName, mbd, instanceWrapper);
// 实例化Bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
if (earlySingletonExposure) {
// 调用getSingleton();
Object earlySingletonReference = getSingleton(beanName, false);
}
return exposedObject;
}
populateBean()
在依赖注入的过程中,会调用getBean()方法创建注入类的实例。只贴核心代码
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 按name注入
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 按type注入
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
}
}
// 随便看一个,按名称注入的
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
// 调用getBean()方法获取bean实例,如果没有,则会创建
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
registerDependentBean(propertyName, beanName);
}
}
}
结语
从上面的一串代码逻辑中可以看出,循环依赖的主要处理逻辑在getSingleton()方法中,但是前提准备工作在createBeanInstance()中。
举例说明:
A依赖B,B也依赖A。
A进行第一步操作,完成了createBeanInstance(),并将自己放入了三级缓存
A进行第二部操作populateBean(A),在注入的过程中,调用getBean(B)创建B的实例。
B调用了getBean(B)后,在createBeanInstance(B)时,发现自己依赖了A,于是调用getBean(A)
此时再进入getsingleton(A)时,一级缓存是没有数据的,二级缓存也没有,但是三级缓存是有A的。
B相当于可以拿到了A对象(虽然不完整,但是可以完成初始化),就能完成整个初始化过程,也就是完整的实例化Bean
B完成初始化后,将自己放入一级缓存,此时回到A对象,A对象也能从一级缓存拿到B对象的实例,也就能完成自己的实例化。
由于B中的A是引用传递,所以此时B中的A引用也就完成了赋值。
A和B都完成了实例化,循环引用完美解决。
Spring通过此方式解决了依赖注入的循环依赖,但是如果是构造器的循环依赖,Spring是无法解决的。
因为三级缓存是在createBeanInstance()之后放入的,但是构造器的赋值是在createBeanInstance()里面执行的。
具体的可以看看createBeanInstance()的autowireConstructor()方法。