了解过spring的小伙伴应该都知道spring默认是支持循环依赖的,那么我们怎么手动关闭spring的循环依赖呢?
话不多说,先看源码:
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");
}
//第四次调用后置处理器,判断是否需要aop
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
//省略后面代码
}
初始化断点调试进来我们看到这里判断是否支持循环依赖是根据 allowCircularReferences这个布尔值来决定的。
/** Whether to automatically try to resolve circular references between beans */
private boolean allowCircularReferences = true;
可以看到spring默认这个属性是为true的,那么我们如何修改这个属性值呢?
我们看到当前方法是属于AbstractAutowireCapableBeanFactory这个类的,这个类一看就知道是一个BeanFactory对象,其实如果我们可以修改spring源码的话,在容器初始化之前,也就是refresh方法执行之前,我们可以加这样一行代码修改这个值的属性来关闭循环依赖:
setAllowCircularReferences(false);
/**
* Create a new AnnotationConfigApplicationContext, deriving bean definitions
* from the given annotated classes and automatically refreshing the context.
* @param annotatedClasses one or more annotated classes,
* e.g. {@link Configuration @Configuration} classes
*/
public AnnotationConfigApplicationContext(Class>... annotatedClasses) {
//这里由于他有父类,故而回先调用父类的构造方法,然后才会调用自己的
//在自己的构造方法中初始一个读取器和扫描器
//beanFactory
this();
setAllowCircularReferences(false);//关闭spring对循环依赖的支持
//annotatedClasses初始化传过来的appconfig类,加载类。register的作用就是把它也加入到bean工厂中
//ac.register(Appconfig.class)
//this.beanDefinitionMap.put(beanName,beanDefinition)
register(annotatedClasses);
refresh();
}
可以看到这个方法内部就是调用BeanFactory来修改这个属性值:
此外spring提供了api来供我们获取beanfactory,我们可以在容器刷新前调用:
public static void main(String[] args) {
AnnotationConfigApplicationContext ac =
new AnnotationConfigApplicationContext();
AbstractAutowireCapableBeanFactory beanFactory = (AbstractAutowireCapableBeanFactory) ac.getBeanFactory();
beanFactory.setAllowCircularReferences(false);
ac.register(AppConfig.class);
ac.refresh();
System.out.println(ac.getBean("city"));
}
以上,感谢阅读。