spring如何解决循环依赖
主要通过三级缓存解决循环依赖,三级缓存分别作用是什么?
1.singletonObjects单例池主要缓存spring单例bean,是经过完整bean生命周期的bean实例。
2.earlySingletonObjects缓存早期单例对象,指未经过属性注入和初始化的bean。
3.singletonFactories缓存的ObjectFactory对象,调用getObject获取单例对象。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
singletonObjects一级缓存何时存入的?当创建bean成功时,会进行缓存升级,将二级三级缓存抹掉,加入到singletonObjects一级缓存。具体加入逻辑在getSingleton方法中,通过调用addSingleton方法。
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
三级缓存singletonFactories是在何时存入的?在createBeanInstance之后就会将早期对象加入singletonFactories。
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
当调用getObject方法时会执行getEarlyBeanReference,主要逻辑是遍历SmartInstantiationAwareBeanPostProcessor调用getEarlyBeanReference方法。
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
循环依赖场景
下面根据一个循环依赖场景,假设A对象内部依赖B,B对象内部依赖A,形成循环依赖,看一下spring解决循环依赖处理流程。
为什么需要三级缓存
spring为什么需要三级缓存,两级缓存能解决循环以来吗?
如果用二级缓存存储代理对象,然后属性注入时去二级缓存找对应的bean,好像也没啥问题。
这样就违背了spring设计原则,因为spring aop是在初始化之后进行的,这样都要改成在实例化之后进行aop,并把代理类加入到二级缓存。