当前位置:   article > 正文

SpringBoot 三级缓存解决循环依赖源码分析_springboot三级缓存

springboot三级缓存

1. 不使用三级缓存可能存在的问题

在 SpringBoot 框架中,如果只存在两级缓存,那么当发生循环依赖的时候可能存在异常的对象创建流程如下图所示:

  1. 创建 A 的空白对象 a1
  2. 解析填充 A 对象的属性,发现依赖的 B 对象未创建,则触发 B 对象创建
  3. 创建 B 对象过程中,填充对象属性时发现依赖 A 对象,此时从缓存中获取到 a1,B 对象创建完毕
  4. A 对象属性填充完成,应用增强切面处理对象 a1,创建了代理对象 a2

可以看到,问题的核心是在 A 对象属性填充完成后再进行代理对象后置创建的处理流程中,可能创建出两个不同的 A 对象,违反默认的单例原则。针对这个问题,解决方式是借助三级缓存提供提前创建代理对象的触发点,并使用缓存标记目标对象的代理已经创建

在这里插入图片描述

2. 源码分析

在这里插入图片描述

2.1 对象实例的创建过程

  1. SpringBoot 框架中的对象工厂实例默认为 DefaultListableBeanFactory,从工厂中获取对象大多数情况下都会调用到其父类实现 AbstractBeanFactory#getBean()。该方法的核心逻辑其实是调用 AbstractBeanFactory#doGetBean() 方法,这个方法需要注意的点如下:

    1. 首先调用父类 DefaultSingletonBeanRegistry#getSingleton() 方法尝试从缓存中获取目标对象,获取到就不用走创建逻辑,本节暂不深入
    2. 缓存中获取不到目标对象,则调用父类重载方法 DefaultSingletonBeanRegistry#getSingleton() 走创建对象逻辑。调用该方法时会将 Lambda 表达式作为 ObjectFactory 的函数式接口实现传入,用于触发对象创建
    3. 调用 AbstractBeanFactory#getObjectForBeanInstance() 处理 FactoryBean 后,返回对象即可
     public Object getBean(String name) throws BeansException {
         return doGetBean(name, null, null, false);
     }
     
     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 {
             // 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.
                 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;
                         }
                     });
                     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;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
  2. DefaultSingletonBeanRegistry#getSingleton() 方法核心逻辑简练,关键点如下:

    1. 首先给第一级缓存加锁防止并发问题,然后检查第一级缓存中没有目标对象才开始创建
    2. 创建对象的步骤并不复杂,首先调用 DefaultSingletonBeanRegistry#beforeSingletonCreation() 方法标记目标对象正在创建中,然后调用传入的函数式实现 ObjectFactory#getObject() 开始创建对象,创建对象完成后调用 DefaultSingletonBeanRegistry#afterSingletonCreation() 方法移除目标对象的创建中标记
    3. 最后调用 DefaultSingletonBeanRegistry#addSingleton() 方法将创建完成的新对象移入第一级缓存中,并将其从其他缓存中移除
     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) {
                     addSingleton(beanName, singletonObject);
                 }
             }
             return singletonObject;
         }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
  3. ObjectFactory#getObject() 的实现在 本节步骤1 中已经提及,实际上最终将调用到 AbstractAutowireCapableBeanFactory#createBean() 方法,该方法的核心逻辑是调用 AbstractAutowireCapableBeanFactory#doCreateBean() 方法

     protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
             throws BeanCreationException {
    
         if (logger.isTraceEnabled()) {
             logger.trace("Creating instance of bean '" + beanName + "'");
         }
         RootBeanDefinition mbdToUse = mbd;
    
         // Make sure bean class is actually resolved at this point, and
         // clone the bean definition in case of a dynamically resolved Class
         // which cannot be stored in the shared merged bean definition.
         Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
         if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
             mbdToUse = new RootBeanDefinition(mbd);
             mbdToUse.setBeanClass(resolvedClass);
         }
    
         // Prepare method overrides.
         try {
             mbdToUse.prepareMethodOverrides();
         }
         catch (BeanDefinitionValidationException ex) {
             throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                     beanName, "Validation of method overrides failed", ex);
         }
    
         try {
             // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
             Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
             if (bean != null) {
                 return bean;
             }
         }
         catch (Throwable ex) {
             throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                     "BeanPostProcessor before instantiation of bean failed", ex);
         }
    
         try {
             Object beanInstance = doCreateBean(beanName, mbdToUse, args);
             if (logger.isTraceEnabled()) {
                 logger.trace("Finished creating instance of bean '" + beanName + "'");
             }
             return beanInstance;
         }
         catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
             // A previously detected exception with proper bean creation context already,
             // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
             throw ex;
         }
         catch (Throwable ex) {
             throw new BeanCreationException(
                     mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
         }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
  4. AbstractAutowireCapableBeanFactory#doCreateBean() 方法并不复杂,核心要点如下:

    1. 首先调用 AbstractAutowireCapableBeanFactory#createBeanInstance() 方法使用反射创建目标类的空白对象
    2. 然后调用 DefaultSingletonBeanRegistry#addSingletonFactory() 方法将获取 当前对象的对象工厂存入第三级缓存
    3. 接着调用 AbstractAutowireCapableBeanFactory#populateBean() 方法填充空白对象的属性
    4. 继续调用 AbstractAutowireCapableBeanFactory#initializeBean() 方法对目标对象做增强处理,包括使用切面创建代理对象等
    5. 最后调用 DefaultSingletonBeanRegistry#getSingleton() 方法从三级缓存中获取的对象,接着校验经过一系列处理后的对象和原始对象是否一致,一致则使用缓存中的对象替换掉原始对象,不一致则说明容器中存在存在多个目标实例需要抛出异常
     protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
    
         // Instantiate the bean.
         BeanWrapper instanceWrapper = null;
         if (mbd.isSingleton()) {
             instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
         }
         if (instanceWrapper == null) {
             instanceWrapper = createBeanInstance(beanName, mbd, args);
         }
         final Object bean = instanceWrapper.getWrappedInstance();
         Class<?> beanType = instanceWrapper.getWrappedClass();
         if (beanType != NullBean.class) {
             mbd.resolvedTargetType = beanType;
         }
    
         // Allow post-processors to modify the merged bean definition.
         synchronized (mbd.postProcessingLock) {
             if (!mbd.postProcessed) {
                 try {
                     applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                 }
                 catch (Throwable ex) {
                     throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                             "Post-processing of merged bean definition failed", ex);
                 }
                 mbd.postProcessed = true;
             }
         }
    
         // Eagerly cache singletons to be able to resolve circular references
         // even when triggered by lifecycle interfaces like BeanFactoryAware.
         boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                 isSingletonCurrentlyInCreation(beanName));
         if (earlySingletonExposure) {
             if (logger.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 {
             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 " +
                                 "'getBeanNamesOfType' 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;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
  5. AbstractAutowireCapableBeanFactory#populateBean() 方法会处理对象内部的属性依赖,核心处理分为以下几步:

    1. 首先调用 RootBeanDefinition#getPropertyValues() 直接从 Bean 定义封装对象中获取目标对象的所有属性
    2. 然后从容器中获取所有后置处理器,使用特定后置处理器 InstantiationAwareBeanPostProcessor#postProcessProperties() 方法来处理对象中依赖的属性
     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 (BeanPostProcessor bp : getBeanPostProcessors()) {
                 if (bp instanceof InstantiationAwareBeanPostProcessor) {
                     InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                     if (!ibp.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 (BeanPostProcessor bp : getBeanPostProcessors()) {
                 if (bp instanceof InstantiationAwareBeanPostProcessor) {
                     InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                     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;
                 }
             }
         }
         if (needsDepCheck) {
             if (filteredPds == null) {
                 filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
             }
             checkDependencies(beanName, mbd, filteredPds, pvs);
         }
    
         if (pvs != null) {
             applyPropertyValues(beanName, mbd, bw, pvs);
         }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
  6. AutowiredAnnotationBeanPostProcessor#postProcessProperties() 方法会处理 @Autowired/@Value/@Inject 标注的属性,核心处理如下:

    1. 调用 AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata() 方法将类中被 @Autowired/@Value/@Inject 标注的属性字段和方法找出来,并将其封装为对应的结构,例如属性字段对应 AutowiredFieldElement
    2. 调用 InjectionMetadata#inject() 方法开始进行依赖的注入
     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;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  7. 对于字段注入,最终将调用到 AutowiredAnnotationBeanPostProcessor#AutowiredFieldElement#inject() 方法执行注入逻辑,关键步骤如下:

    1. 首先调用 DefaultListableBeanFactory#resolveDependency() 通过对象工厂处理依赖,最终会调用到 DefaultListableBeanFactory#getBean() 方法获取依赖的对象。如果当前存在 A->B->A 循环依赖,则创建 B 对象的流程为 本节步骤1-7 的重复,最终将调用 DefaultListableBeanFactory#getBean() 方法去获取创建中的 A 对象,这部分下节继续分析
    2. 获取到依赖对象后,通过反射将其注入到指定字段
         protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
             Field field = (Field) this.member;
             Object value;
             if (this.cached) {
                 value = resolvedCachedArgument(beanName, this.cachedFieldValue);
             }
             else {
                 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();
                 try {
                     value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
                 }
                 catch (BeansException ex) {
                     throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
                 }
                 synchronized (this) {
                     if (!this.cached) {
                         if (value != null || this.required) {
                             this.cachedFieldValue = desc;
                             registerDependentBeans(beanName, autowiredBeanNames);
                             if (autowiredBeanNames.size() == 1) {
                                 String autowiredBeanName = autowiredBeanNames.iterator().next();
                                 if (beanFactory.containsBean(autowiredBeanName) &&
                                         beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                                     this.cachedFieldValue = new ShortcutDependencyDescriptor(
                                             desc, autowiredBeanName, field.getType());
                                 }
                             }
                         }
                         else {
                             this.cachedFieldValue = null;
                         }
                         this.cached = true;
                     }
                 }
             }
             if (value != null) {
                 ReflectionUtils.makeAccessible(field);
                 field.set(bean, value);
             }
         }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

2.2 三级缓存的处理

  1. 在上一节步骤1中,笔者提到从容器中获取对象时首先是从缓存中获取,则对于创建中的对象 A ,首先将调用 DefaultSingletonBeanRegistry#getSingleton() 方法从内部三级缓存中获取实例,需要注意的点如下:

    1. 首先从第一级缓存 singletonObjects 中获取已经创建完成的单例对象
    2. 如果第一级缓存中获取不到,判断当前要获取的对象是否在创建中,如是则从第二级缓存 earlySingletonObjects 中获取
    3. 如果第二级缓存中获取不到,判断是否允许使用提前暴露的引用来获取对象,如是则从第三级缓存 singletonFactories 中获取到对象工厂,调用对象工厂方法获取对象。获取到对象后,将其存入第二级缓存,并将对象工厂从第三级缓存中移除
    public Object getSingleton(String beanName) {
         return getSingleton(beanName, true);
     }
    
     /**
      * Return the (raw) singleton object registered under the given name.
      * <p>Checks already instantiated singletons and also allows for an early
      * reference to a currently created singleton (resolving a circular reference).
      * @param beanName the name of the bean to look for
      * @param allowEarlyReference whether early references should be created or not
      * @return the registered singleton object, or {@code null} if none found
      */
      protected Object getSingleton(String beanName, boolean allowEarlyReference) {
         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;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
  2. 在 上一节步骤4 笔者提到第三级缓存实际是存放到对象工厂,通过对象工厂的函数式接口来实现获取对象,则此处将触发 AbstractAutowireCapableBeanFactory#getEarlyBeanReference() 方法执行。可以看到这里的核心处理是遍历 SmartInstantiationAwareBeanPostProcessor 后置处理器对目标对象进行处理,在此过程中 AnnotationAwareAspectJAutoProxyCreator#getEarlyBeanReference() 方法将被调用,最终执行了其父类实现 AbstractAutoProxyCreator#getEarlyBeanReference()

     protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
         Object exposedObject = bean;
         if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
             for (BeanPostProcessor bp : getBeanPostProcessors()) {
                 if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                     SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                     exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                 }
             }
         }
         return exposedObject;
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  3. AbstractAutoProxyCreator#getEarlyBeanReference() 方法的关键处理分为两步:

    1. 首先生成该对象的缓存 key,并将原始对象存入内部 earlyProxyReferences 缓存中,需注意该缓存是为了避免重复创建目标对象的代理对象
    2. 调用 AbstractAutoProxyCreator#wrapIfNecessary() 方法搜索查找需要应用在目标对象上的增强切面,找到后就通过动态代理创建代理对象
    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;
         }
         if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
             return bean;
         }
         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;
         }
    
         this.advisedBeans.put(cacheKey, Boolean.FALSE);
         return bean;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
  4. 以上方法执行完毕,B 对象创建完成,回到最初创建对象 A 的流程中。此时对象 A 的属性填充完成,开始执行 AbstractAutowireCapableBeanFactory#initializeBean() 对目标对象执行增强处理,此处的核心如下:

    1. 首先调用 AbstractAutowireCapableBeanFactory#invokeAwareMethods() 方法执行目标对象的相关自省方法,填充特定属性
    2. 调用 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization() 方法遍历后置处理器列表,执行处理器 BeanPostProcessor#postProcessBeforeInitialization() 方法对目标对象执行实例化前的增强
    3. 调用 AbstractAutowireCapableBeanFactory#invokeInitMethods() 方法判断目标对象是否实现了 InitializingBean 接口,是则执行对应接口方法
    4. 调用 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization() 方法遍历后置处理器列表,执行处理器 BeanPostProcessor#postProcessAfterInitialization() 方法对目标对象执行实例化后的增强,这一步将触发 AbstractAutoProxyCreator#postProcessAfterInitialization() 方法为目标对象创建代理
    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
         if (System.getSecurityManager() != null) {
             AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                 invokeAwareMethods(beanName, bean);
                 return null;
             }, getAccessControlContext());
         }
         else {
             invokeAwareMethods(beanName, bean);
         }
    
         Object wrappedBean = bean;
         if (mbd == null || !mbd.isSynthetic()) {
             wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
         }
    
         try {
             invokeInitMethods(beanName, wrappedBean, mbd);
         }
         catch (Throwable ex) {
             throw new BeanCreationException(
                     (mbd != null ? mbd.getResourceDescription() : null),
                     beanName, "Invocation of init method failed", ex);
         }
         if (mbd == null || !mbd.isSynthetic()) {
             wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
         }
    
         return wrappedBean;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
  5. AbstractAutoProxyCreator#postProcessAfterInitialization() 方法的处理如下,可以看到这部分基本与 本节步骤3 的逻辑相呼应,如果 earlyProxyReferences 缓存中存在目标对象标记,则证明已经为目标对象创建过代理对象了,不需要再重新创建,从而避免多个代理对象存在造成的不一致问题

     public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
         if (bean != null) {
             Object cacheKey = getCacheKey(bean.getClass(), beanName);
             if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                 return wrapIfNecessary(bean, beanName, cacheKey);
             }
         }
         return bean;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

3. 遗留问题

从源码分析中可以看到,三级缓存解决循环依赖中的动态代理问题主要依赖 AbstractAutoProxyCreator#earlyProxyReferences 缓存。但是需注意,当存在特殊的 BeanPostProcessor 对目标对象额外进行代理增强时,AbstractAutoProxyCreator#earlyProxyReferences 缓存标记就失效了,此时依然会产生循环依赖异常

例如 A->B->A 循环依赖中,如果 A 被 @Async 注解并通过 @EnableAsync 开启了异步特性,则必将抛出循环依赖异常

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/919804
推荐阅读
相关标签
  

闽ICP备14008679号