在某一次面试中,对方问了一个问题:Spring的Bean如果互相依赖,会发生什么?由于我那段时间正好遇到了一个Spring循环依赖报错的问题,就回答会报错。然后听对方口气,感觉自己答错了。于是事后了解了一下,才发现其实Spring自身解决了循环依赖的问题。
Spring的启动后,会读取配置文件,资源文件读取校验,创建BeanFactory,解析配置文件创建BeanDefinition,注册到BeanFactory,注册各种默认处理器,加载国际化、事件广播、监听器等,最后实例化非延迟初始化的单例。
代码关键点如下:
AbstractApplicationContext.refresh() //加载配置,启动容器
AbstractApplicationContext.finishBeanFactoryInitialization()
DefaultListableBeanFactory.preInstantiateSingletons() //实例化单例
AbstractBeanFactory.getBean() //获取bean,触发创建
AbstractBeanFactory.doGetBean()
DefaultSingletonBeanRegistry.getSingleton() //获取bean触发bean的创建并缓存
AbstractAutowireCapableBeanFactory.createBean() //InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()提前创建bean
AbstractAutowireCapableBeanFactory.doCreateBean() //创建bean
AbstractAutowireCapableBeanFactory.populateBean() //注入
AbstractAutowireCapableBeanFactory.initializeBean() //初始化,afterPropertiesSet、initMethod、Aware注入、postProcessAfterInitialization()
以一个简单循环依赖为例,两个普通的互相依赖的Bean(非延迟初始化的单例)。
@Component
public class ServiceA {
private ServiceB serviceB;
public ServiceA() {
System.out.println("ServiceA()");
}
public void foo() {
System.out.println("serviceA.foo()");
serviceB.foo();
}
@Autowired
public void setServiceB(ServiceB serviceB) {
System.out.println("serviceA.setServiceB()");
this.serviceB = serviceB;
}
}
@Component
public class ServiceB {
private ServiceA serviceA;
public ServiceB() {
System.out.println("serviceB()");
}
public void foo() {
System.out.println("serviceB.foo()");
}
@Autowired
public void setServiceA(ServiceA serviceA) {
System.out.println("serviceB.setServiceA()");
this.serviceA = serviceA;
}
}
@Configuration
@ComponentScan
public class SetMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainApplication.class);
System.out.println("start");
context.getBean(ServiceA.class).foo();
}
}
执行后,会打印
ServiceA()
ServiceB()
serviceB.setServiceA()
serviceA.setServiceB()
start
serviceA.foo()
serviceB.foo()
可以发现,Spring启动先后创建了ServiceA、ServiceB实例,但是先调用了ServiceB的set方法注入ServiceA,然后调用ServiceA的set方法注入ServiceB,并未报错。可见Spring在启动的时候,就把循环依赖处理掉了。于是跟踪查看源码:
- Spring启动时会调用AbstractApplicationContext.refresh(),加载并解析配置文件,创建BeanDefinition,加载并执行各种PostProcessors等,最后初始化剩余的非延迟初始化的单例(……)
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 准备,设置其启动时间、活动标志、初始化属性源
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 解析配置,创建Beanfactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 配置BeanFactory,例如默认ClassLoader和各种处理器
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 允许在上下文子类中对bean工厂进行后处理。
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 执行所有注册为bean的BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册BeanPostProcessor bean
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 初始化MessageSource,用于国际化
initMessageSource();
// Initialize event multicaster for this context.
// 初始化事件广播
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 初始化特定上下文子类中的其他特殊bean。
onRefresh();
// Check for listener beans and register them.
// 检查监听器bean并注册它们
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 实例化所有剩余的(非延迟初始化)单例
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
} catch (BeansException ex) {
...
} finally {
...
}
}
}
}
- 获取所有bean名字,当bean满足非抽象、单例、非延迟初始化条件时,调用getBean()触发bean初始化。
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
@Override
public void preInstantiateSingletons() throws BeansException {
...
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 非抽象、单例、非延迟初始化
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext());
} else {
isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
} else {
// 不是FactoryBean,普通bean
getBean(beanName);
}
}
}
...
}
}
- 尝试获取bean,如果取不到,就创建
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 急切地检查单例缓存以手动注册单例。
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// 获取不到,bean没有被创建
// Fail if we're already creating this bean instance: We're assumably within a circular reference.
// 如果我们已经在创建这个bean实例,则失败: 我们假设在一个循环引用中。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 从parent中获取bean
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
} else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 处理@DependsOn
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
// 创建bean实例
if (mbd.isSingleton()) {
// 获取/创建
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
...
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
...
} catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
}
}
- 开始真正创建bean,首先实例化对象,然后执行注入,并执行各种初始化回调和初始化方法
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
if (instanceWrapper == null) {
//创建实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
...
// Eagerly cache singletons to be able to resolve circular references even when triggered by lifecycle interfaces like BeanFactoryAware.
// 急切地缓存(敏感词?)单例,以便在像BeanFactoryAware这样的生命周期接口触发时也能够解析循环引用。
// 单例、允许循环依赖(AbstractAutowireCapableBeanFactory.setAllowCircularReferences())、单例正在创建中(DefaultSingletonBeanRegistry.getSingleton()时加入的)
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));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//填充bean,注入
populateBean(beanName, mbd, instanceWrapper);
//初始化bean,执行各种回调、初始化方法等
exposedObject = initializeBean(beanName, exposedObject, mbd);
} catch (Throwable ex) {
...
}
return exposedObject;
}
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
...
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//ImportAwareBeanPostProcessor、AutowiredAnnotationBeanPostProcessor
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
...
}
}
- 注入是通过AutowiredAnnotationBeanPostProcessor完成的
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
} catch (BeanCreationException ex) {
throw ex;
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
}
- 以方法注入为例,根据方法获取参数类型,并从BeanFactory中获取,通过反射调用方法,完成注入
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {
...
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
...
Method method = (Method) this.member;
Object[] arguments;
if (this.cached) {
// Shortcut for avoiding synchronization...
arguments = resolveCachedArguments(beanName);
} else {
Class<?>[] paramTypes = method.getParameterTypes();
arguments = new Object[paramTypes.length];
DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
Set<String> autowiredBeans = new LinkedHashSet<>(paramTypes.length);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
for (int i = 0; i < arguments.length; i++) {
MethodParameter methodParam = new MethodParameter(method, i);
DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
currDesc.setContainingClass(bean.getClass());
descriptors[i] = currDesc;
try {
// 获取依赖
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
if (arg == null && !this.required) {
arguments = null;
break;
}
arguments[i] = arg;
} catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
}
}
...
if (arguments != null) {
try {
// 反射注入
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);
} catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
}
}
- 对于普通bean,获取依赖最终会调用到AbstractBeanFactory.getBean()。此时开始创建ServiceB,过程跟ServiceA一致。当创建完ServiceB后,需要注入ServiceA时,会再次来到AbstractBeanFactory.getBean()。这次情况就不一样了,因为在创建ServiceA的时候,singletonsCurrentlyInCreation中保存了beanName。
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
...
//beanName加入singletonsCurrentlyInCreation
beforeSingletonCreation(beanName);
...
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (IllegalStateException ex) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
} catch (BeanCreationException ex) {
...
} finally {
...
}
if (newSingleton) {
//创建bean完成
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
// 首次创建ServiceA时,保存了beanName
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
//把bean放入singletonObjects
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);
}
}
}
同时,在创建ServiceA时保存了ObjectFactory,并传入了刚刚创建的ServiceA对象。
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//刚new的对象
final Object bean = instanceWrapper.getWrappedInstance();
...
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");
}
//设置单例工厂,设置singletonFactories,把bean传入
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
...
}
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
//默认情况全部返回bean,不做修改
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
}
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
// 第一次创建ServiceA时,保存ObjectFactory
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
}
当ServiceB尝试获取ServiceA时,就会从singletonFactories中获取ObjectFactory,调用工厂获取之前放入的ServiceA对象。所以这里会直接返回新创建且没有初始化的ServiceA(serviceB=null)对象,并注入到ServiceB中。ServiceB初始化完成之后,将返回ServiceB(serviceA=servieA(serviceB=null))对象注入到ServiceA中,此时ServiceB(serviceA=servieA(serviceB=serviceB))中的ServiceA对象也就包含了ServiceB的引用了。至此,循环依赖就完成了。
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 急切地检查单例缓存以手动注册单例。
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
...
}
}
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
//第一次,返回false,执行创,DefaultSingletonBeanRegistry.getSingleton(String,ObjectFactory)#beforeSingletonCreation保存了beanName
//第二次,返回true
//bena创建完成后从singletonObjects能直接获取
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) {
// 调用工厂创建,AbstractAutowireCapableBeanFactory.doCreateBean()#addSingletonFactory()设置的
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
}
这个功能的要点就在DefaultSingletonBeanRegistry.getSingleton()中,当创建ServiceA时,会把ObjectFactory放入singletonFactories中,当创建ServiceB需要注入ServiceA时,获得ObjectFactory,拿到ServiceA对象,并放入earlySingletonObjects中,这个过程中有其他bean依赖ServiceA就可以直接从earlySingletonObjects获取。当ServiceA初始化过程完成,把bean放入singletonObjects,当其他bean依赖ServiceA时,直接从singletonObjects中获取。
可见,Spring解决了循环依赖问题,那为什么我会遇到报错呢。因为我接手了IDE的建议,把注入方式改成了构造方法注入。
@Component
public class ServiceA {
private final ServiceB serviceB;
@Autowired
public ServiceA(ServiceB serviceB) {
System.out.println("ServiceA()");
this.serviceB = serviceB;
}
public void foo() {
System.out.println("serviceA.foo()");
serviceB.foo();
}
}
@Component
public class ServiceB {
private final ServiceA serviceA;
@Autowired
public ServiceB(ServiceA serviceA) {
System.out.println("ServiceB()");
this.serviceA = serviceA;
}
public void foo() {
System.out.println("serviceB.foo()");
}
}
@Configuration
@ComponentScan
public class ConstructorMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConstructorMain.class);
System.out.println("start");
context.getBean(ServiceA.class).foo();
}
}
执行后Spring启动报错,告知依赖的bean正在创建中,可能有循环引用
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'serviceA': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:374)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:250)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:192)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:273)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1247)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1177)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:857)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:760)
... 28 more
因为用构造方法注入后,在创建对象时必须传入依赖,如果两个bean互相引用,就必须对方先现实化,产生“死循环”,从逻辑上就有问题。而在Spring里对这种场景的处理,前面步骤基本一致:
- 创建ServiceA实例,发现ServiceA是构造方法注入,根据构造方法参数类型,从BeanFactory查找ServiceB。
- 创建ServiceB实例,发现ServiceB是构造方法注入,根据构造方法参数类型,从BeanFactory查找ServiceA。
- 由于ServiceA目前还在实例化,并没有走到缓存那一步,所以获取不到ServiceA的实例化对象。于是触发创建bean,由于在创建ServiceA时保存了singletonsCurrentlyInCreation,所以此时检验发现ServiceA正在创建中,于是抛出异常。
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// 由于ServiceA尚未初始化,所以这里取不到
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
...
} else {
try {
...
// 创建
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
...
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
...
}
} catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
...
return (T) bean;
}
}
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
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) {
...
// ServiceA创建时beanName加入singletonsCurrentlyInCreation
// 当ServiceB试图获取ServiceA时,检查
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (IllegalStateException ex) {
...
} catch (BeanCreationException ex) {
...
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//beanName从singletonsCurrentlyInCreation移除
afterSingletonCreation(beanName);
}
...
}
return singletonObject;
}
}
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
protected void beforeSingletonCreation(String beanName) {
// 当创建ServiceB并试图获取ServiceA时,由于ServiceA仍然在创建中,所以报错
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
}
所以当使用构造方法注入时,Spring无法解决循环依赖。
总结,Spring自动解决循环依赖的条件:
- 使用字段或set方法注入
- bean的scope必须是singleton
- 启用循环依赖支持(AbstractAutowireCapableBeanFactory.setAllowCircularReferences(boolean)),默认启用
同时,解决问题最好的办法就是避免发生问题,比如:在方法内通过BeanFactory.getBean()获取或者依赖的方法抽象出来放到第三个bean里。
相关代码(基于Spring 5.1.3.RELEASE)
https://github.com/dingfugui/spring-notes/tree/master/spring-circular-dependencies