说到Spring的循环依赖,我们常会提起过三级缓存,那三级缓存究竟是什么?又有什么作用?Spring是怎么实现循环依赖的?带着这些问题,我们一起来开启这篇文章。
我们先来看看Spring官网关于循环依赖的介绍。Spring官网循环依赖介绍
Spring官网中关于循环依赖,还有下面一段介绍。
您通常可以相信 Spring 会做正确的事情。它在容器加载时检测配置问题,例如对不存在的 bean 的引用和循环依赖关系。Spring 在实际创建 bean 时尽可能晚地设置属性并解析依赖项。这意味着,如果在创建对象或其依赖项时出现问题,那么正确加载的 Spring 容器可以在以后请求对象时生成异常ーー例如,由于缺少或无效的属性,bean 会抛出异常。某些配置问题的可见性可能会延迟,这就是为什么在缺省情况下 ApplicationContext 实现会预实例化单例 bean 的原因。在实际需要这些 bean 之前创建它们需要预先花费一些时间和内存,在创建 ApplicationContext 时发现配置问题,而不是在以后。您仍然可以覆盖此默认行为,以便单例 bean 可以延迟初始化,而不是急切地预实例化。
如果不存在循环依赖关系,当一个或多个协作 bean 被注入到依赖 bean 中时,每个协作 bean 在被注入到依赖 bean 之前都被完全配置。这意味着,如果 bean A 依赖于 bean B,Spring IoC 容器将在调用 bean A 上的 setter 方法之前完全配置 bean B。换句话说,bean 被实例化(如果它不是预实例化的单例) ,它的依赖项被设置,相关的生命周期方法(如配置的 init 方法或 InitializingBean 回调方法)被调用。
我们可以理解为Spring中的bean会经过一系列的生命周期,如,实例化,初始化(属性填充),初始化方法执行前,完成AOP代理,对象销毁方法执行后等,完成这些流程才是一个完整的bean,但在存在循环依赖的时候,生命周期就卡在初始化时的属性填充操作中,这时,Spring会对bean进行提前暴露,先完成AOP代理等,再将提前暴露的对象注入进来。这些操作会需要借助三级缓存和对象工厂完成,所以Spring说需要预先花费一些时间和内存。
我们先来看一段代码。
@Component
public class CycleA {
@Autowired
public CycleB cycleB;
public CycleA() {
System.out.println("CycleA");
}
}
@Component
public class CycleB {
@Autowired
public CycleA cycleA;
public CycleB() {
System.out.println("CycleB");
}
}
上面的CycleA引用CycleB,CycleB引用CycleA,因此CycleA和CycleB存在循环依赖关系。其次我们要明白循环依赖发生在什么时候?属性注入时。
由于Spring循环依赖比较绕,我们就通过断点调试的方式追踪代码。由于我们的依赖是通过@Autowired进行注入的,前面也详细讲解了@Autowired依赖注入的源码分析(@Autowired依赖注入源码分析),为了节省时间,快速定位到循环依赖发生的地方,我们将断点打在@Autowired进行属性注入的地方。
@SuppressWarnings("deprecation") // for postProcessPropertyValues
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
……省略
/**
* @see org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry registry,Object source)
*/
//调用第六次后置处理器
//这里的BeanPostProcessor是由spring启动时注入的,这里使用了策略模式,
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
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) {
//应用PropertyValues,将pvs应用于bw中
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
我们知道@Autowired注解的解析是通过AutowiredAnnotationBeanPostProcessor后置处理器完成的,如果不熟悉AutowiredAnnotationBeanPostProcessor的解析@Autowired注解流程或者想重温@Autowired注解解析流程,可以将断点打在其postProcessProperties()方法中。断点条件设置为beanName.equals("cycleA")。由于我这边比较熟悉这部分的代码,也为了节省中间步骤,我直接将断点打在DefaultListableBeanFactory的doResolveDependency()方法上。
属性注入的实质是先从容器中获取对应的属性的实例,再完成属性设值。
protected T doGetBean(
String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object bean;
//代码块二:从缓存中获取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 {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 如果子容器中不能存在,那就从父容器中找
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) {
//代码块三:标记Bean正在创建,设置相关状态的值
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
// 代码块四:合并bd,就是如果当前bd有父bd的话,要将父bd的属性也整合当当前bd中(跟继承类似,子类拥有父类的属性特征)
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 合并后的bd不能是抽象类,不然抛出异常
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
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);
}
}
}
//代码块七:创建单例bean
// Create bean instance.
// 单例bean才有循环依赖
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建bean
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;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
我们需要明白,此时CycleB还没有进行实例化,也没有正在被创建,所以isSingletonCurrentlyInCreation(beanName)返回false。所以这里返回null。
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
/**
* 一级缓存
* 缓存成品bean:正常完成生命周期的bean
*/
/** Cache of singleton objects: bean name to bean instance. */
private final Map singletonObjects = new ConcurrentHashMap<>(256);
/**
* 二级缓存
* 缓存进行提前暴露bean的工厂,方便后续调用
*/
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map> singletonFactories = new HashMap<>(16);
/**
* 三级缓存
* 缓存半成品对象(提前暴露的对象)
*/
/** Cache of early singleton objects: bean name to bean instance. */
private final Map earlySingletonObjects = new ConcurrentHashMap<>(16);
/**
* spring三级缓存:
* 一级缓存:singletonObjects
* 二级缓存:singletonFactories
* 三级缓存:earlySingletonObjects
* 循环依赖会用到三级缓存
*/
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
//从单例池中获取bean
Object singletonObject = this.singletonObjects.get(beanName);
//isSingletonCurrentlyInCreation是否正在创建
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
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) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
}
既然bean不是正在被创建,那Spring就准备着手创建这个bean。
这个方法大致总结为:
1)如果alreadyCreated(已经被创建的bean对应的beanName集合)集合中不包含当前beanName。则进行下面的步骤。
2)获取当前beanName对应的BD,如果BD不为null,将BD的属性值stale设置为true。(这个标识表示确定是否需要重新合并definitions,因为这里是刚准备着手创建,自然还没有进行合并BD,所以将这个值设置为true)。
3)从当前mergedBeanDefinitions中移除该BD,表示正在已被创建或正在被创建。
4)将当前beanName加入alreadyCreated集合。
// 标记bean已经创建或正在被创建
protected void markBeanAsCreated(String beanName) {
if (!this.alreadyCreated.contains(beanName)) {
synchronized (this.mergedBeanDefinitions) {
// 双检锁
if (!this.alreadyCreated.contains(beanName)) {
// Let the bean definition get re-merged now that we're actually creating
// the bean... just in case some of its metadata changed in the meantime.
// 从当前mergedBeanDefinitionHolders中移除该bd,表示正在已被创建或正在被创建
clearMergedBeanDefinition(beanName);
this.alreadyCreated.add(beanName);
}
}
}
}
@Override
protected void clearMergedBeanDefinition(String beanName) {
super.clearMergedBeanDefinition(beanName);
this.mergedBeanDefinitionHolders.remove(beanName);
}
protected void clearMergedBeanDefinition(String beanName) {
RootBeanDefinition bd = this.mergedBeanDefinitions.get(beanName);
if (bd != null) {
// 确定是否需要重新合并definitions
bd.stale = true;
}
}
就是如果当前bd有父bd的话,要将父bd的属性也整合当当前bd中(跟Java类的继承类似,子类对象拥有父类的属性和特征)。
这个方法大致总结为:
1)获取当前beanName对应的mergedBeanDefinition(这里获取到mergedBeanDefinition不weinull)。
2)mergedBeanDefinition为null或其stale属性为true(这里为true,上面设置了true值),表示需要合并bd。
3)如果当前bd没有父bd,bd是RootBeanDefinition类型的,直接clone()一个对象,如果不是,根据bd构建RootBeanDefinition对象。
4)如果当前bd有父bd,获取父bd的属性,并根据父bd构建RootBeanDefinition对象,并将子bd的属性复制给这个RootBeanDefinition对象。
5)将这个合并后的bd放入mergedBeanDefinitions集合中。
6)从缓存中复制相关属性到这个合并的bd中。
合并完成后的bd的stale属性为false(默认值为false,且属性复制的时候没有复制这个属性值),表示不再需要合并bd。
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
RootBeanDefinition previous = null;
// Check with full lock now in order to enforce the same merged instance.
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
// mbd.stale = true
if (mbd == null || mbd.stale) {
previous = mbd;
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
mbd = new RootBeanDefinition(bd);
}
}
else {
// Child bean definition: needs to be merged with parent.
BeanDefinition pbd;
try {
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without a ConfigurableBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
mbd = new RootBeanDefinition(pbd);
mbd.overrideFrom(bd);
}
// Set default singleton scope, if not configured before.
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(SCOPE_SINGLETON);
}
// A bean contained in a non-singleton bean cannot be a singleton itself.
// Let's correct this on the fly here, since this might be the result of
// parent-child merging for the outer bean, in which case the original inner bean
// definition will not have inherited the merged outer bean's singleton status.
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// Cache the merged bean definition for the time being
// (it might still get re-merged later on in order to pick up metadata changes)
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
if (previous != null) {
// 代码块六:从缓存中复制相关属性
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
return mbd;
}
}
将子bd的属性复制给RootBeanDefinition对象。
public void overrideFrom(BeanDefinition other) {
if (StringUtils.hasLength(other.getBeanClassName())) {
setBeanClassName(other.getBeanClassName());
}
if (StringUtils.hasLength(other.getScope())) {
setScope(other.getScope());
}
setAbstract(other.isAbstract());
if (StringUtils.hasLength(other.getFactoryBeanName())) {
setFactoryBeanName(other.getFactoryBeanName());
}
if (StringUtils.hasLength(other.getFactoryMethodName())) {
setFactoryMethodName(other.getFactoryMethodName());
}
setRole(other.getRole());
setSource(other.getSource());
copyAttributesFrom(other);
if (other instanceof AbstractBeanDefinition) {
AbstractBeanDefinition otherAbd = (AbstractBeanDefinition) other;
if (otherAbd.hasBeanClass()) {
setBeanClass(otherAbd.getBeanClass());
}
if (otherAbd.hasConstructorArgumentValues()) {
getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
}
if (otherAbd.hasPropertyValues()) {
getPropertyValues().addPropertyValues(other.getPropertyValues());
}
if (otherAbd.hasMethodOverrides()) {
getMethodOverrides().addOverrides(otherAbd.getMethodOverrides());
}
Boolean lazyInit = otherAbd.getLazyInit();
if (lazyInit != null) {
setLazyInit(lazyInit);
}
setAutowireMode(otherAbd.getAutowireMode());
setDependencyCheck(otherAbd.getDependencyCheck());
setDependsOn(otherAbd.getDependsOn());
setAutowireCandidate(otherAbd.isAutowireCandidate());
setPrimary(otherAbd.isPrimary());
copyQualifiersFrom(otherAbd);
setInstanceSupplier(otherAbd.getInstanceSupplier());
setNonPublicAccessAllowed(otherAbd.isNonPublicAccessAllowed());
setLenientConstructorResolution(otherAbd.isLenientConstructorResolution());
if (otherAbd.getInitMethodName() != null) {
setInitMethodName(otherAbd.getInitMethodName());
setEnforceInitMethod(otherAbd.isEnforceInitMethod());
}
if (otherAbd.getDestroyMethodName() != null) {
setDestroyMethodName(otherAbd.getDestroyMethodName());
setEnforceDestroyMethod(otherAbd.isEnforceDestroyMethod());
}
setSynthetic(otherAbd.isSynthetic());
setResource(otherAbd.getResource());
}
else {
getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
getPropertyValues().addPropertyValues(other.getPropertyValues());
setLazyInit(other.isLazyInit());
setResourceDescription(other.getResourceDescription());
}
}
private void copyRelevantMergedBeanDefinitionCaches(RootBeanDefinition previous, RootBeanDefinition mbd) {
if (ObjectUtils.nullSafeEquals(mbd.getBeanClassName(), previous.getBeanClassName()) &&
ObjectUtils.nullSafeEquals(mbd.getFactoryBeanName(), previous.getFactoryBeanName()) &&
ObjectUtils.nullSafeEquals(mbd.getFactoryMethodName(), previous.getFactoryMethodName())) {
ResolvableType targetType = mbd.targetType;
ResolvableType previousTargetType = previous.targetType;
if (targetType == null || targetType.equals(previousTargetType)) {
mbd.targetType = previousTargetType;
mbd.isFactoryBean = previous.isFactoryBean;
mbd.resolvedTargetType = previous.resolvedTargetType;
mbd.factoryMethodReturnType = previous.factoryMethodReturnType;
mbd.factoryMethodToIntrospect = previous.factoryMethodToIntrospect;
}
}
}
这个方法大致总结为:
1)先去单例池中获取beanName对应的bean对象。如果获取不到,进行下面的步骤。
2)准备创建bean之前的工作。(主要检查bean是否需要创建,及将当前beanName标记为正在创建(加入正在创建的bean集合中))。
3)根据对象工厂实例化单例bean。
4)创建bean完成之后,将当前beanName从正在创建的集合中移除。并将新创建的bean加入单例池中。
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 + "'");
}
//代码块八:创建bean之前的准备工作(检查和状态设置)
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) {
// 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;
}
//创建bean完成之后,将当前beanName从正在创建的集合中移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
//是否是新创建的bean,如果是,加入单例池中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
这里主要做了两件事情。
1)检查该beanName是否被排除的bean(不需要Spring进行创建的bean,可以进行配置)
2)将beanName加入singletonsCurrentlyInCreation集合,表示正在被创建,这个是set集合,重复加入则抛出异常。
protected void beforeSingletonCreation(String beanName) {
// 检查该beanName是否被排除的bean(不需要Spring进行创建的bean,可以进行配置)
// 将beanName加入singletonsCurrentlyInCreation集合,表示正在被创建,这个是set集合,不能重复加入
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
singletonObject = singletonFactory.getObject();
……
@FunctionalInterface
public interface ObjectFactory {
/**
* Return an instance (possibly shared or independent)
* of the object managed by this factory.
* @return the resulting instance
* @throws BeansException in case of creation errors
*/
T getObject() throws BeansException;
}
……
//代码块七:创建单例bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建bean
return createBean(beanName, mbd, args);
}
这里省略一些推断构造方法及实例化对象的过程,这些前面都详细分析过了(推断构造器源码分析),我们重点看看Spring解决循环依赖的地方。这里调用构造器已经将bean(CycleB)实例化出来了,现在在进行属性填充前,Spring会先解决循环依赖问题。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//第二次调用后置处理器的入口方法(推断构造方法)
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
……
/**
* 主动缓存单例,以便能够解析循环引用
* 即使被BeanFactoryAware这样的生命周期接口触发。
*/
//spring解决循环依赖的地方
// 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");
}
//第四次调用后置处理器,看看是否需要aop
//代码块十一:添加对象创建工厂的缓存,用于生产提前暴露的bean
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//填充属性
//调用第五次和第六次后置处理器的地方
populateBean(beanName, mbd, instanceWrapper);
//调用第七次和第八次后置处理器的地方
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
……
return exposedObject;
}
如果单例池中没有这个bean对应的beanName,设置singletonFactories(二级缓存)为创建对象的半成品工厂singletonFactory。同时从earlySingletonObjects(三级缓存)中移除beanName对应的缓存。
ObjectFactory里面是只有一个接口方法getObject(),这边应用lamba表达式,getObject()会调用getEarlyBeanReference() ,但addSingletonFactory()中并没有调用getEarlyBeanReference() 方法,真正用到ObjectFactory.getObject() 时才会执行getEarlyBeanReference()。
protected void addSingletonFactory(String beanName, ObjectFactory singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
//singletonFactory是一个半成品的对象工厂
//为什么存储对象工厂?提前暴露工厂
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
// !mbd.isSynthetic()非合成类
//
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
对应的实现类为AbstractAutoProxyCreator。
// 获取bean的早期引用
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
如果符合被代理的条件,生成对应的代理对象。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
//调用第一个后置处理器时对不需要代理的bean完成了this.advisedBeans.put(cacheKey,false)的操作
// 不需要代理的bean包括,已经完成代理的bean(配置类、普通类)和定义为切面,切点或通知的bean
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 代码块十四:返回给定bean类是否表示基础结构类,它不应该被代理的。
// shouldSkip()表示一些要求返回怨声实例的bean不应该被代理(原始实例beanName的后缀为.ORIGINAL,etc:com.mypackage.MyClass.ORIGINAL)
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
//找出所有的切面和通知
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 代码块十五:创建代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
// 已经完成代理的bean设置为false
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
本身是用来描述AOP的bean不应该被代理。
protected boolean isInfrastructureClass(Class beanClass) {
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
if (retVal && logger.isTraceEnabled()) {
logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
}
return retVal;
}
protected Object createProxy(Class beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
//创建一个代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
//将当前对象的信息赋值给工厂
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
/**
* @see DefaultAopProxyFactory#createAopProxy(AdvisedSupport)
*/
return proxyFactory.getProxy(getProxyClassLoader());
}
执行完这部分代码后,CycleB进入属性填充的代码,要把CycleA注入进来。
第二次进入这个方法,最终会调用getBean(cycleA) ,上次是调用getBean(cycleB)。
CycleA对应的对象工厂不为null。
spring中默认只支持单例bean的循环依赖,且不能是构造器注入,只能set注入才能实现循环依赖。
一是因为要区分完整的对象和半成品对象。
二是因为二级缓存是工厂,产生一个对象需要执行创建对象的流程,在创建对象的时候需要提前完成aop等流程,比较繁琐,在beanClass固定的情况下,无论调用多少次工厂方法产生的对象(半成品)都是相同的,所以为了提高效率,将生产出来的对象放到三级缓存中。
并不是所有的对象都需要用到循环依赖,对于不需要循环依赖的对象,那执行工厂方法就没有意义,而且创建半成品对象的流程也比较繁琐,会造成性能消耗。
一般对象的生命周期都是在对象完成属性注入之后才会进行aop,但是在循环依赖的时候,可能无法按正常的流程完成属性注入,工厂方法就是将这些无法正常完成属性注入的对象提前完成aop,方便后续调用。