循环依赖的分类
-
主要分为属性注入的循环依赖和构造器注入的循环依赖,先来看属性注入的循环依赖,解决的核心在于singletonFactories这个缓存
- 总的逻辑是:首先从Spring容器中获取A的Bean时,调用createBeanInstance实例化构造函数之后,把A对应的实例化对象存入singletonFactories,接着在属性赋值populateBean这一步,会解析A的依赖属性b,通过DefaultListableBeanFactory的doResolveDependency,从容器中又去获取B对应的Bean
- 同样B实例化的过程与A一样(至此A只完成了实例化,没有开始初始化),B完成实例化之后,把B对应的实例化对象存入singletonFactories,开始populateBean解析依赖的属性a,同样在DefaultListableBeanFactory的doResolveDependency,从容器中又去获取A对应的Bean,由于第一步A存在于第三级缓存singletonFactories中,可以通过调用ObjectFactory的getObject方法(实质是调用lambda中,SmartInstantiationAwareBeanPostProcessor类型的后置处理器的getEarlyBeanReference方法)返回单例对象,同时放入二级缓存earlySingletonObjects,并且移除三级缓存
- B的属性赋值就完成,接着完成B剩下的初始化过程,最后程序的栈帧回退到第一步中A的populateBean方法,由于B依赖的a已完成赋值,A依赖的b就也完成赋值,至此相互引用的对象都有完整的值,解析完成。
- 源码分析如下:
/*--------------------------- 示例代码 ------------------------*/
@Component
public class A {
@Autowired
private B b;
public void handleA() {
System.out.println("调用A的handleA方法");
}
}
@Component
public class B {
@Autowired
private A a;
}
- 在从Spring Ioc容器中获取A对应的Bean时,首先调用AbstractBeanFactory的getBean,在doGetBean中,第一次调用getSingleton(beanName),从singletonObjects中取,当然获取不到,返回null,进行接下来的流程
// 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 + "'");
}
}
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 对于单例,会运行下面的逻辑
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
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;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
- 对于单例,调用getSingleton(String beanName, ObjectFactory<?> singletonFactory)
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 (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
// 将beanName放入singletonsCurrentlyInCreation
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 调用AbstractBeanFactory的lambda表达式,即:AbstractAutowireCapableBeanFactory的createBean方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// // 将beanName从singletonsCurrentlyInCreation中移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 把创建好的单例对象singletonObject放入一级缓存,即:单例缓存池中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
- 首先尝试从singletonObjects中获取,如果获取不到,把当前bean标记为正在创建
- singletonFactory.getObject()调用createBean,再继续调用doCreateBean,分为三步:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// factoryBeanInstanceCache存储的是:beanName对应的FactoryBean实例对象
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 根据构造函数实例化,创建Bean实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 返回的是原始对象,创建的Bean中属性值为null
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 {
// 扩展点 TODO
// 此步骤功能点包括:AutowiredAnnotationBeanPostProcessor对@Autowired预解析
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.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 此时bean没有完成属性注入,构造一个ObjectFactory放入第三级缓存singletonFactories中,
// 便于下面的getSingleton方法,从singletonFactories中取出并执行lambda表达式
// 第三级缓存,为了应对当前Bean在后面出现循环依赖的情况,就可以通过lambda表达式进行AOP的逻辑
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
// 对象已经暴露出去
Object exposedObject = bean;
try {
// 填充属性@Autowired
populateBean(beanName, mbd, instanceWrapper);
// 初始化Bean、应用BeanPostProcessor
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 " +
"'getBeanNamesForType' 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;
}
- 通过反射,根据构造函数实例化createBeanInstance(此时A依赖的属性b,为null)
- 接下来判断,如果满足条件:单例 && 允许循环依赖 && 正在创建中,把当前beanName放入第三级缓存singletonFactories中
- 调用populateBean开始属性填充
- 此时A依赖的属性b,b被@Autowired标注,在doResolveDependency中,判断出B的类型是Class,然后执行b的Bean的获取逻辑,即:getBean("b")
- 执行流程与创建a对应的Bean的逻辑相同,当执行到populateBean时,判断出a的类型是Class,然后执行a的Bean的获取逻辑,即:getBean("a"),重点关注populateBean方法中,AutowiredAnnotationBeanPostProcessor后置处理器的处理过程
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
} else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 构造函数注入,set方法注入,@Value注入的逻辑在此处完成
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
- AutowiredAnnotationBeanPostProcessor的属性赋值逻辑
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// @Autowired的预解析在populateBean这一步之前,applyMergedBeanDefinitionPostProcessors中进行的,解析结果会存入缓存,这里直接从缓存中取
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;
}
- InjectionMetadata的inject函数
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
// 对每个@Autowired标识的属性进行注入,根据element的类型不同(解析字段或者解析函数),执行不同的逻辑,这里选择字段解析
element.inject(target, beanName, pvs);
}
}
}
- AutowiredFieldElement(AutowiredAnnotationBeanPostProcessor的内部类)的inject逻辑
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
try {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
value = resolveFieldValue(field, bean, beanName);
}
}
else {
// 解析字段的值
value = resolveFieldValue(field, bean, beanName);
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
// 给当前对象的属性逐一赋值
field.set(bean, value);
}
}
- 解析字段的值
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
Object value;
try {
// 解析依赖的属性值,如果是对象,会重新调用getBean的逻辑,代码需要一步步的跟
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
Object cachedFieldValue = null;
if (value != null || this.required) {
cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
this.cachedFieldValue = cachedFieldValue;
this.cached = true;
}
}
return value;
}
- DefaultListableBeanFactory的解析依赖函数(构造器注入的循环依赖@Lazy解决点)
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
} else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
} else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
} else {
// 对于构造器注入的循环依赖,添加@Lazy注解可以解决,下面一行代码是解决的关键
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
-
doResolveDependency是核心,真正解析依赖,这里顺便说一下,@Value注解,以及数组类型、Collection类型、Map类型的注入,@Autowired的注入解析逻辑都在这里完成,根据不同的条件,运行对应的处理逻辑
- 这里解析@Autowired,先找到候选的bean,
- 如果有多个bean,如:同一个接口存在多个实现类,根据@Primary决定候选的bean
- 否则,直接取出候选的bean名称和对应的类型instanceCandidate,
- 对于还没有在Spring Ioc容器中创建的依赖项,某属性还没有经过完整的生命周期,通过此步骤往单例缓存池中存入对应的bean(对应到源码中的逻辑是:instanceCandidate instanceof Class判断条件)
- 【说明】:找候选的bean的函数findAutowireCandidates源码,这里暂时不展示,里面的逻辑也值得研究。
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
// 解析@Value注解
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
// 考虑属性的不同情况:数组类型、Collection类型、Map类型
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 解析@Autowired依赖的多个bean,找到真正的候选bean
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
// 如果有多个bean,如:同一个接口存在多个实现类,根据@Primary决定候选的bean
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
} else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
// 对于还没有在Spring Ioc容器中创建的依赖项,如:orange属性还没有经过完整的生命周期,通过此步骤往单例缓存池中存入对应的bean
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
- 构造器注入的循环依赖
/*--------------------------- 示例代码 ------------------------*/
@Component
public class A {
private B b;
// 如果是构造器循环依赖,加上Spring的@Lazy注解可以不报错
//@Lazy
@Autowired
public A(B b) {
System.out.println("A的有参构造函数");
this.b = b;
}
public void handleA() {
System.out.println("调用A的handleA方法");
}
}
@Component
public class B {
private A a;
@Autowired
public B(A a) {
System.out.println("B的有参构造函数");
}
}
- 如果不加@Lazy注解,因为放入三级缓存的操作是在createBeanInstance实例化构造函数之后进行的,对于构造函数注入的循环依赖Spring无法解决,通过debug源码得知,构造函数A依赖的b解析时,B又会调用a的实例化过程,在整个过程中,singletonFactories还没来得及做remove操作,导致getSingleton(String beanName, ObjectFactory<?> singletonFactory) 这个调用中,beforeSingletonCreation中singletonsCurrentlyInCreation对a的add操作不成功,导致抛异常BeanCurrentlyInCreationException
- 而如果加了@Lazy注解,解决的逻辑源码在“DefaultListableBeanFactory的解析依赖函数”这一步,返回的result不为空,直接返回,不用运行重新获取依赖属性的操作,换句话说,A依赖的b,可以直接找到,A对象能顺利完成初始化操作,不会抛异常
总结
- Spring只能解决属性注入的循环依赖,无法解决构造器注入的循环依赖
- 对于构造器注入的循环依赖,可通过加上@Lazy注解避免报错