spring循环引用
spring在默认单例的情况下是支持循环引用的
代码体现在AbstractAutowireCapableBeanFactory#doCreateBean方法中
(boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));)
isSingleton是否是单例 ,allowCircularReferences 默认是true,可以通过api关闭循环依赖。
通过AbstractAutowireCapableBeanFactory#setAllowCircularReferences(false)方法关闭
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
setAllowCircularReferences( false );
refresh();
}
循环依赖示例代码
package com.cycle;
@Component
public class A {
@Autowired
B b;
int ac=5;
}
package com.cycle;
@Component
public class B {
@Autowired
A a;
int bc=3;
}
debug过程
根据beanName=a,获取getBean(a)
getbean.png
调用到doGetBean(a)方法
doGetBean.png
进入getSingleton方法
getSingleton.png
首先设置此时正在创建a,放入集合。调用getObject进入lamdba表达式createBean
getObject.png
createBean调用到doCreateBean
createBean.png
创建bean
经过推断构造方法,缓存注解信息,暴露对象工厂,到属性填充
doCreateBean.png
属性填充
populateBean.png
调用后置处理器进行属性填充(模版方法)
AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
postProcessPropertyValues.png
注入
inject.png
elementinject.png
resolveDependency.png
doResolveDependency.png
resolveCandidate.png
BeanFactorygetBean.png
getBeanB.png
所谓循环依赖,就是A含有B的属性,B含有A的属性。
从debug大概流程:getBean(beanName)说起,首先需要创建A,A需要填充属性B,注入B需要从BeanFactory(Bean工厂)查询B是否存在,现在肯定不存在则继续创建B,B需要填充属性A,再次从bean工厂查询,到这里则A能查询到。(此时将会经过spring后置处理器全部过程)
getSingletona.png
singletonFactorygetObject.png
此时,A正在创建isSingletonCurrentlyInCreation(a)返回true,将会从singletonFactories得到。得到之后放到earlySingletonObjects中,并把singletonFactories中移除,并一直返回并进行属性set 。B注入从singletonFactories查询到的A对象
getEarlyBeanReference.png
BPPgetEarlyReference.png
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
fieldset.png
fieldsetAfter.png
A注入B之后,经过B的生命周期,返回得到带有A属性的B对象。B注入到A之中,最终效果如下图
AfieldsetB.png
再经过A 的其他生命周期过程。完成循环依赖过程
方法参考
singletonsCurrentlyInCreation添加正在被创建bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
添加单例工厂,提前暴露工厂
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
getSingleton()方法
bean:首先得是一个对象,然后这个对象需要经历一系列的bean生命周期(bean后置处理器处理过程)
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
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;
}
AbstractAutowireCapableBeanFactory#doCreateBean源码
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @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);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
//第三次后置处理器 缓存注解信息
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// 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) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//第四次 后置处理器 暴露对象到singlentonfactories集合中 解决循环依赖问题
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//填充属性
//第五次 是否需要填充属性
//第六次 填充属性
populateBean(beanName, mbd, instanceWrapper);
//初始化bean
//第七次
//第八次 aop
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
AbstractAutoProxyCreator#getEarlyBeanReference 处理代理类
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
总结:
getSingleton()方法是解决循环依赖的关键。
有三个缓存集合
1、singletonObjects
bean放到里面,经历完整生命周期
2、singletonFactories
存放生成对象的工厂 是一个表达式 (包含对象) 对象需要改变,改变之后放到3
如果依赖的对象需要实现aop,则需要在这里存一个能够完成生成代理类的工厂。如果不在这里代理则注入的对象没有代理功能
参考AbstractAutoProxyCreator#getEarlyBeanReference方法
3、earlySingletonObjects
工厂生成的对象,此时生命周期没有走完。如果还有其他地方引用就不需要再通过2再次生成
关键点:
1、singletonsCurrentlyInCreation集合
当创建bean时,将首先DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory<?>)表达式中
beforeSingletonCreation(beanName)加进去
2、addSingletonFactory方法
通过方法addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));添加到singletonFactories。当再次调用时ObjectFactory的实现类AbstractAutowireCapableBeanFactory$lambda的getObject()方法最终调用getEarlyBeanReference方法,返回bean实例