源码分析1:三级缓存
假设单例A、单例B之间循环依赖
假设先创建A
org.springframework.context.support.AbstractApplicationContext#getBean(java.lang.String)
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
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) {...}
if (logger.isDebugEnabled()) {...}
//1.标记A正在创建中
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {...}
try {
//实际会调用createBean方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {...}
catch (BeanCreationException ex) {...}
finally {...}
if (newSingleton) {...}
}
return singletonObject;
}
}
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {...}
//实例化阶段
if (instanceWrapper == null) {...}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {...}
// Allow post-processors to modify the merged bean definition.
//BeanDefintion后置处理阶段
synchronized (mbd.postProcessingLock) {...}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 急切地缓存单例,以便能够解析循环引用,即使是由BeanFactoryAware等生命周期接口触发的。
// 是单例、且允许循环依赖(allowCircularReferences默认是true)、
// 且当前Bean正在创建中(getSingleton的时候已经标记创建中了)
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {...}
//2. 添加三级缓存
// 往三级缓存中添加ObjectFactory
// 此时还不知道会不会出现循环依赖,后面也许会用到,也许用不到。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//属性填充阶段(假设A要注入B,注入的过程中最终会再次调getBean拿B)
populateBean(beanName, mbd, instanceWrapper);
//初始化阶段
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {...}
if (earlySingletonExposure) {...}
// Register bean as disposable.
try {...}
catch (BeanDefinitionValidationException ex) {...}
return exposedObject;
}
可以让容器关闭循环依赖:
1.标记A正在创建中
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#beforeSingletonCreation
protected void beforeSingletonCreation(String beanName) {
//inCreationCheckExclusions:当前从创建检查中排除的bean的名称。
//singletonsCurrentlyInCreation:往这个集合中添加元素,如果已经存在返回false,说明已经在创建中了
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
2. 添加三级缓存
是单例、且允许循环依赖(allowCircularReferences默认是true)、且当前Bean正在创建中,则添加三级缓存。
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingletonFactory
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
//singletonFactories三级缓存
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
A属性填充阶段注入B
创建A的过程中,到了属性填充阶段,就会开始注入B了,此时会再次调getBean找B
…
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object beanInstance;
// Eagerly check singleton cache for manually registered singletons.
// 1. 先从单例池中找B,肯定找不到B,且B还没有开始创建
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {...}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {...}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {...}
if (!typeCheckOnly) {...}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {...}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {...}
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
//2. 创建单例B
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {...}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {...}
else {...}
}
catch (BeansException ex) {...}
finally {...}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
1. 先从单例池中找B
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String)
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
// 此时单例池中是找不到B的,并且B还没有在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {...}
return singletonObject;
}
检查是否正在创建中:
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#isSingletonCurrentlyInCreation
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
此时单例池中是找不到B的,并且B还没有在创建中,所以会开始创建B。
同理B也会先标记B正在创建中,然后添加三级缓存,到了B属性填充阶段,会去注入A
B属性填充阶段注入A
创建B的过程中,到了属性填充阶段开始注入A,此时会再次调getBean找A
…
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object beanInstance;
// Eagerly check singleton cache for manually registered singletons.
// 急切地检查手动注册的单例缓存。
// 1.从三级缓存中找A
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {...}
else {...}
return adaptBeanInstance(name, beanInstance, requiredType);
}
1. 从三级缓存中找A
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String)
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
//allowEarlyReference:是否允许创建早期引用
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
// 此时单例池中是找不到A的,但是发现A已经在创建中了
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//去二级缓存拿,此时也拿不到的
singletonObject = this.earlySingletonObjects.get(beanName);
//拿不到判断是否允许创建早期引用,此时allowEarlyReference=true
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) {
//执行三级缓存的getObject拿到最终需要注入的对象
//此时如果是AOP则返回代理对象,不是AOP返回普通对象
singletonObject = singletonFactory.getObject();
//将三级缓存生成的对象(最终注入的对象)放到二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
//用不到了,就移除了
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
//此时返回"半成品"对象
return singletonObject;
}
解决循环依赖,其实核心代码就两段逻辑,一个是放入三级缓存,一个从三个缓存中取值
源码分析2:AOP情况针对循环依赖的处理
保证不会重复AOP生成代理对象
如果发生循环依赖,且是AOP情况,会提前生成代理对象
而正常流程是在初始化后生成代理对象的
所以初始化后这里肯定要做一个控制,如果已经提前进行过AOP就不能再进行AOP了
看下提前进行AOP执行的代码:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getEarlyBeanReference
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
//提前AOP,代表发生循环依赖,且会调getEarlyBeanReference
//正常AOP,无论是否发生循环依赖,都会调postProcessAfterInitialization
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
只关心AOP的实现:
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getEarlyBeanReference
//发生循环依赖才会调用这个方法,提前获取bean引用
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
//记录一下当前Bean发生了循环依赖,并提前获取Bean引用了
//即记录当前Bean进行了AOP,注意此时bean是原始对象
this.earlyProxyReferences.put(cacheKey, bean);
//AOP,返回代理对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
//同时对比一下初始化后执行的方法,无论是否发生循环依赖都会执行
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
//earlyProxyReferences里取的是null != bean,说明之前没进行过AOP,才会进行AOP
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//当前正在创建的Bean不用进行AOP,比如切面Bean
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 判断当前Bean是否存在匹配的advice,如果存在则要生成一个代理对象
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
//advisedBeans记录了某个Bean已经进行过AOP了
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
//要AOP,返回代理对象
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
//不要AOP,返回普通对象
return bean;
}
保证最终单例池里放入正确的对象
A在初始化后发现已经提前AOP了,就不会再进行AOP了,之后要把A放到单例池里去
思考一下,此时放到单例池里的是原始对象还是代理对象?
再看一下初始化后的方法:
AOP的实现:
即初始化后方法得到的对象,有两种情况:
- 如果提前AOP了(发生循环依赖了),初始化后方法得到的就是原始对象
- 如果没有提前AOP(没有发生循环依赖),初始化后方法得到的就是代理对象
如果发生循环依赖,提前AOP生成代理对象,虽然在初始化后阶段不会重复生成代理对象,但返回出去的是原始对象,而最终放入单例池的肯定希望是AOP的代理对象,那从哪里获得?二级缓存。
看下初始化后之后做了什么:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {... }
//实例化阶段
if (instanceWrapper == null) {...}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {...}
//BeanDefinition后置处理
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {...}
// 循环依赖 - 设置三级缓存
// 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) {...}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//属性填充阶段
populateBean(beanName, mbd, instanceWrapper);
//初始化阶段(初始化前、初始化、初始化后)
//注意,如果没有发生循环依赖,这里得到的就是代理对象
//如果发生了循环依赖,这里得到的就是原始对象(大部分情况)
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {...}
//关键这里!!
if (earlySingletonExposure) {//如果支持循环依赖
//再次getBean,此时会从二级缓存拿到对象!!此时二级缓存存的就是“最终的"对象引用
//本质是执行多次SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference得到的对象
Object earlySingletonReference = getSingleton(beanName, false);
//能拿到,说明发生了循环依赖!!!
if (earlySingletonReference != null) {
//发生循环依赖以后
//exposedObject:初始化后得到的对象
//bean:一开始实例化的原始对象
//比较 初始化后拿到的对象 和 一开始实例化的原始对象
if (exposedObject == bean) {//大部分情况肯定一样的,先考虑简单场景
//一样的话拿二级缓存的,替换exposedObject,最终返回
//所以哪怕发生循环依赖,也能正常返回最终的那个代理对象
exposedObject = earlySingletonReference;
}
//下面这段逻辑是处理:初始化后替换的对象 与 提前获取引用生成的对象 不一样冲突的情况
//比较复杂,感兴趣就看https://www.yuque.com/qhao/framework/dxfpaw#FjcPV
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {...}
}
// Register bean as disposable.
try {...}
catch (BeanDefinitionValidationException ex) {...}
return exposedObject;
}
所以哪怕发生循环依赖,也能通过二级缓存,正常返回最终的那个代理对象