前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面试必问系列之最强源码分析,带你一步步弄清楚Spring如何解决循环依赖(二)

面试必问系列之最强源码分析,带你一步步弄清楚Spring如何解决循环依赖(二)

原创
作者头像
huc_逆天
发布2024-01-22 23:19:04
1310
发布2024-01-22 23:19:04

对于Spring框架或者Springboot框架使用的小伙伴们,不管是面试还是实际工作中,面临的一个非常频繁的问题就是如何解决循环依赖。本文就是从源码分析角度,一步步弄清楚循环依赖的前世今生,以及如何正确的有效解决它!

我们在面试必问系列之最强源码分析,带你一步步弄清楚Spring如何解决循环依赖(一)中,通俗易懂的描述了循环依赖的含义,以及如何产生的,同时,讲了Spring管理Bean的方式。本文继续上文,解读循环依赖的解决。

Spring如何解决循环依赖

当我们能够明确了上述学习之后,我想,我们可以进入到源码的世界中去分析了。

查看解决循环依赖,也就是了解Spring是如何对Bean对象进行实例化、初始化的。

知识点:

对象的创建分为两部分,一部分为实例化,此时,在堆内存中分配了内存空间,但是未对其属性进行赋值,另一部分为初始化,完成对于实例化后对象的属性的赋值操作。因此类对象在内存空间中,两种状态,实例化状态(实例化完成、未初始化),完全状态(实例化完成、初始化完成)

一切的开始

以XML文件为例,代码如下,进入debug模式,走起,跟上队伍!

代码语言:java
复制
public class SpringTestApplication {
   public static void main(String[] args) {
       ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
  }
}
第一站

进入到,上下文的处理构造器中,看代码,找重点。

代码语言:java
复制
public ClassPathXmlApplicationContext(
    String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
    throws BeansException {
    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
            // 此处是我们的第一站
    refresh();
    }
}

refresh方法,在AbstractApplicationContext内。代码内部,做了点什么事情呢,可以详细的看看代码注释。

代码语言:java
复制
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 完成准备,设置时间啊等等,我们无需太关心
prepareRefresh();
// 无需多关心
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// bean factory 创建前的准备阶段,对应我们上述图的流程
prepareBeanFactory(beanFactory);
try {
               //BeanFactory的处理过程,跟我们的对象创建关系不大 开始
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
               //BeanFactory的处理过程,跟我们的对象创建关系不大 完成
// Instantiate all remaining (non-lazy-init) singletons.
               //实例化,所有的非懒加载的单例bean对象,可见第二站入口来了,开启
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
第二站,真正的入口

看这个前,我们有必要了解一个类对象,其中提供了三个缓存对象

代码语言:java
复制
DefaultSingletonBeanRegistry
/** Cache of singleton objects: bean name to bean instance. */
// 一级缓存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
// 三级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
// 二级缓存
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

记住,对应的对象名,后续在源码中会依次出现。

回到第二站,查看相关源码,直接查看注释中中文标记点,继续追踪

代码语言:java
复制
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}

// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}

// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}

// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);

// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();

// Instantiate all remaining (non-lazy-init) singletons.
       // 实例化,所有的非懒加载的单例bean对象
beanFactory.preInstantiateSingletons();
}

跳转,DefaultListableBeanFactory

代码语言:java
复制
    @Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}

// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

// Trigger initialization of all non-lazy singleton beans...
       // 根据BeanDefinition 获取bean定义信息
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
           // 首先 A对象 此处非抽象类 单例 非懒加载才能进入,A对象符合条件,进入
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 {
                   //A对象 进入
getBean(beanName);
}
}
}

// 省略
}

再到,AbstractBeanFactory

代码语言:java
复制
@Override
public Object getBean(String name) throws BeansException {
       // Spring源码内 do开头,都是真正做事情的方法
return doGetBean(name, null, null, false);
}
第三站 创建bean

AbstractBeanFactory

查看中文代码注释部分,快速定位。按照代码执行序号,查看逻辑。

代码语言:java
复制
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.
      // 1. 获取单例bean对象 第四站入口
    Object sharedInstance = getSingleton(beanName);
      // 根据第四站代码分析,此时A对象为空,返回空,将继续执行
    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) {
        markBeanAsCreated(beanName);
      }

      try {
        final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
        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);
            }
          }
        }

        // Create bean instance.
                // 3. 创建对象
        if (mbd.isSingleton()) {
                    // 进入方法
          sharedInstance = getSingleton(beanName, () -> {
            try {
                            // 5. 创建对象 实现A 对象实例
              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();
          final 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 BeanCreationException(beanName,
                "Scope '" + scopeName + "' is not active for the current thread; consider " +
                "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                ex);
          }
        }
      }
      catch (BeansException ex) {
        cleanupAfterBeanCreationFailure(beanName);
        throw ex;
      }
    }

    // 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;
  }
第四站

DefaultSingletonBeanRegistry

代码语言:java
复制
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
       // 2.
       // 一级缓存中查找,是否存在bean A对象,此时为空
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;
}
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
       // 4. 执行对象处理
synchronized (this.singletonObjects) {
           // 一级缓存中获取A 对象,无
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 + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
                   // 获取对象 ObjectFactory<?> 通过匿名内部类执行,匿名内部类 ,获取到A实例化对象,此时A 为实例化状态,创建中
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;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}

执行匿名内部类 创建A 对象

代码语言:java
复制
AbstractAutowireCapableBeanFactory
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) {
           //实例A创建
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.
       // 此处 A对象已创建,会进入判断
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");
}
           //三级缓存,放入实例化对象A 此时A 未完全状态 缓存内状态,见代码下图示
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
           // 6. 填充bean
populateBean(beanName, mbd, instanceWrapper);
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;
}

缓存内部状态

填充bean属性内容

代码语言:java
复制
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 省略
if (pvs != null) {
           //处理属性内容
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
// 省略代码
// Create a deep copy, resolving any references for values.
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
               // B对象
String propertyName = pv.getName();
               // 值为 null
Object originalValue = pv.getValue();
if (originalValue == AutowiredPropertyMarker.INSTANCE) {
Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
if (writeMethod == null) {
throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
}
originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
}
               // 7. 解决B对象
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
//省略代码
}

BeanDefinitionValueResolver

代码语言:java
复制
@Nullable
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
// We must check each value to see whether it requires a runtime reference
// to another bean to be resolved.
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
           //B对象作为A对象属性值,类型为RuntimeBeanReference 进入判断,执行方法resolveReference
return resolveReference(argName, ref);
}
// 省略代码
@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
Object bean;
Class<?> beanType = ref.getBeanType();
if (ref.isToParent()) {
BeanFactory parent = this.beanFactory.getParentBeanFactory();
if (parent == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Cannot resolve reference to bean " + ref +
" in parent factory: no parent factory available");
}
if (beanType != null) {
bean = parent.getBean(beanType);
}
else {
                   // A对象依赖B对象,获取B对象
bean = parent.getBean(String.valueOf(doEvaluate(ref.getBeanName())));
}
}
//省略代码

开始B对象的获取

第五站 依赖对象 B生成

重新回到

代码语言:java
复制
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);
}
   //省略代码

类似A对象的处理,此处忽略

最终到了,处理B对象属性A对象,上述描述6 。此时,缓存情况如下:

进一步补充属性,即完成B对象中属性A对象的获取。

重新进入doGetBean ,进入 getSingleton

代码语言:java
复制
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
       // 此时一级缓存中获取A对象,同样 A对象为空,此时一级缓存中不存在
Object singletonObject = this.singletonObjects.get(beanName);
       // A对象状态为 实例化 因此,在创建中,进入判断
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
               
               // 二级缓存中获取 A对象 ,A对象为空,进入判断
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
                   //三级缓存中获取 A对象,可以读取到值
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
                       // 将A 对象放入 二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
                       // 将A 对象从三级缓存中删除
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}

此时,缓存情况如下:

处理完B对象的属性A对象后,B对象此时变为初始化完成、实例化完成,成为完全态

代码语言:java
复制
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 + "'");
}
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;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
                   // 8. A对象属性对象 B对象完成初始化后执行
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
代码语言:java
复制
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
           // 一级缓存放入 B对象 完全态
this.singletonObjects.put(beanName, singletonObject);
           // 三级缓存删除 B对象
this.singletonFactories.remove(beanName);
           // 二级缓存删除 B对象
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}

此时,缓存情况如下:

此时A对象中属性B对象,完成初始化,A对象会执行以下代码

代码语言:java
复制
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
           // 一级缓存放入 A对象 完全态
this.singletonObjects.put(beanName, singletonObject);
           // 三级缓存删除 A对象
this.singletonFactories.remove(beanName);
           // 二级缓存删除 A对象
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}

此时,缓存情况如下:

第六站 遍历Bean对象 B
代码语言:java
复制
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}

// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

// Trigger initialization of all non-lazy singleton beans...
       // 根据BeanDefinition 获取bean定义信息
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
           // 首先 A对象 此处非抽象类 单例 非懒加载才能进入,A对象符合条件,进入
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 {
                   //B对象 进入
getBean(beanName);
}
}
}

// 省略
}
故事结尾

最后直接返回,因为完全态在一级缓存中都存在了。

终于结束了,带着大家走了一遍源码,不知道你能理解多少。

从以上源码,我们可以看到,Spring采用三级缓存,来实现循环依赖的解决。

常见的面试问题

• 循环依赖必须使用三级缓存么

其实,从我们解读看来,只需要把对象的两个状态处理好,就能处理好循环依赖的问题,因此实际上来说,不必要使用三级缓存对于一般的bean对象来讲。

• 为何Spring解决三级缓存要使用三级缓存,而不是二级缓存

为何Spring采用三级缓存,其实主要是因为Bean对象不仅仅是基础的一般对象,还会有一些AOP后期增强对象,通过Cglib或者JDK动态代理手段,织入的对象。二级缓存,只能满足一般Bean对象的处理,无法处理更多的对象。

再看三级缓存

代码语言:java
复制
/** Cache of singleton objects: bean name to bean instance. */
// 一级缓存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
// 三级缓存 返回值类型 泛型为 ObjectFactory<?> 能够处理更多的事项
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
// 二级缓存
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

以上就比较明确,为何使用三级而不是二级了

总结

看源码就是需要细致认真的解读,因此需要耐心。希望读着也能有耐心看下去。如果你可以,我相信,你对于循环依赖,不会有什么难点。

我正在参与2024腾讯技术创作特训营第五期有奖征文,快来和我瓜分大奖

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring如何解决循环依赖
    • 一切的开始
      • 第一站
        • 第二站,真正的入口
          • 第三站 创建bean
            • 第四站
              • 第五站 依赖对象 B生成
                • 第六站 遍历Bean对象 B
                  • 故事结尾
                  • 常见的面试问题
                  • 总结
                  相关产品与服务
                  腾讯云代码分析
                  腾讯云代码分析(内部代号CodeDog)是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档