spring getBean的三级缓存有点绕,但理清楚了,就会发现也挺简单的。
一、循环依赖
循环依赖有多种情况,以下整理的三种:
1、构造方法互相依赖
例如ServiceA的构造方法中依赖了ServiceB, Service的构造方法中依赖了ServiceA
public class ServiceA {
private ServiceB serviceB;
public ServiceA(ServiceB serviceB){
this.serviceB = serviceB;
}
}
public class ServiceB {
private ServiceA serviceA;
public ServiceB(ServiceA serviceA){
this.serviceA = serviceA;
}
}
2、属性互相依赖
例如ServiceA的field或者setter方法依赖ServiceB, 同时ServiceB也如此依赖ServiceA
public class ServiceA {
@Autowired
private ServiceB serviceB;
}
public class ServiceB {
@Autowired
private ServiceA serviceA;
}
3、构造方法依赖&属性依赖
例如:
例如ServiceA的构造方法中依赖了ServiceB
ServiceB的field或者setter方法依赖ServiceA
public class ServiceA {
private ServiceB serviceB;
public ServiceA(ServiceB serviceB){
this.serviceB = serviceB;
}
}
public class ServiceB {
@Autowired
private ServiceA serviceA;
}
第1种情况(构造方法互相依赖)Spring也无解,会抛出BeanCreationException, 异常信息:“Circular depends-on relationship between ‘serviceA’ and ‘serviceB’”
1、2两个情况都是spring可以处理的。
二、Spring循环依赖的理论依据
Spring循环依赖的理论依据其实是Java基于引用传递,当我们获取到对象的引用时,对象的field或者或属性是可以延后设置的。
Spring单例对象的初始化其实可以分为三步:(实例化、填充属性、初始化)
createBeanInstance ## 实例化
↓
populateBean ## 填充属性
↓
initializeBean ## 初始化
- createBeanInstance
实例化,实际上就是调用对应的构造方法构造对象,此时只是调用了构造方法,spring xml中指定的property并没有进行赋值 - populate
populateBean,填充属性,这步对spring xml中指定的property进行填充 - initializeBean
调用spring xml中指定的init方法,或者AfterPropertiesSet方法
三、三级缓存
对于单例对象来说,在Spring的整个容器的生命周期内,有且只存在一个对象,这个对象存在Cache中,Spring大量运用了Cache的手段,在循环依赖问题的解决过程中甚至使用了“三级缓存”。
“三级缓存”主要是指:
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
...
/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
...
}
从字面意思来说:
singletonObjects指单例对象的cache;
earlySingletonObjects指提前曝光的单例对象的cache;
singletonFactories指单例对象工厂的cache;
以上三个cache构成了三级缓存,Spring就用这三级缓存巧妙的解决了循环依赖问题。
可以理解为三个桶,例如:
假设:A和B的field互相依赖
1、先尝试获取A,A在所有缓存中都没有;
2、创建A的实例,并封装成一个ObjectFactory放入三级缓存;
3、填充A属性field B;
4、尝试获取B,B在所有缓存中都没有;
5、创建B的实例,并封装成一个ObjectFactory放入三级缓存;
6、填充B属性field a;
7、先尝试获取A,A在三级缓存中存在,获取三级缓存中的ObjectFactory对象返回A,并将A放入二级缓存,从三级缓存中删除
8、将A赋值给B.a
9、初始化B
10、将B加入一级缓存,并从二级、三级缓存中删除
11、返回B
12、将B赋值给A.b
13、初始化A
14、将A加入一级缓存,并从二级、三级缓存中删除
15、返回A
流程示意图如下:
下面将利用到缓存的核心代码贴出来,不相关的代码去掉:
AbstractBeanFactory#doGetBean
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 从缓存中获取Bean, #@see DefaultSingletonBeanRegistry#getSingleton(String beanName, boolean allowEarlyReference)
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
...
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
...
try {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
...
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建Bean,加入三级缓存,填充属性,初始化都在这个方法中, @see AbstractAutowireCapableBeanFactory#doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
...
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
...
return (T) bean;
}
从缓存中获取Bean的代码逻辑: DefaultSingletonBeanRegistry#getSingleton(String, boolean )
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
**创建Bean的代码逻辑:**AbstractAutowireCapableBeanFactory#doCreateBean(String, RootBeanDefinition, Object[])
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
//创建实例
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//创建实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
...
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
...
// 添加三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 填充属性
populateBean(beanName, mbd, instanceWrapper);
// 初始化, 执行BeanPostProcessor
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
...
}
...
return exposedObject;
}
上面的代码就是spring IoC Bean三级缓存的执行逻辑。
附一张debug的调用链: