1. 不使用三級緩存可能存在的問題
在 SpringBoot 框架中,如果只存在兩級緩存,那么當(dāng)發(fā)生循環(huán)依賴的時(shí)候可能存在異常的對象創(chuàng)建流程如下圖所示:
- 創(chuàng)建 A 的空白對象 a1
- 解析填充 A 對象的屬性,發(fā)現(xiàn)依賴的 B 對象未創(chuàng)建,則觸發(fā) B 對象創(chuàng)建
- 創(chuàng)建 B 對象過程中,填充對象屬性時(shí)發(fā)現(xiàn)依賴 A 對象,此時(shí)從緩存中獲取到 a1,B 對象創(chuàng)建完畢
- A 對象屬性填充完成,應(yīng)用增強(qiáng)切面處理對象 a1,創(chuàng)建了代理對象 a2
可以看到,問題的核心是在 A 對象
屬性填充
完成后再進(jìn)行代理對象后置創(chuàng)建
的處理流程中,可能創(chuàng)建出兩個(gè)不同的 A 對象,違反默認(rèn)的單例原則。針對這個(gè)問題,解決方式是借助三級緩存提供提前創(chuàng)建代理對象的觸發(fā)點(diǎn),并使用緩存標(biāo)記目標(biāo)對象的代理已經(jīng)創(chuàng)建
2. 源碼分析
2.1 對象實(shí)例的創(chuàng)建過程
-
SpringBoot 框架中的對象工廠實(shí)例默認(rèn)為
DefaultListableBeanFactory
,從工廠中獲取對象大多數(shù)情況下都會調(diào)用到其父類實(shí)現(xiàn)AbstractBeanFactory#getBean()
。該方法的核心邏輯其實(shí)是調(diào)用AbstractBeanFactory#doGetBean()
方法,這個(gè)方法需要注意的點(diǎn)如下:- 首先調(diào)用父類
DefaultSingletonBeanRegistry#getSingleton()
方法嘗試從緩存中獲取目標(biāo)對象,獲取到就不用走創(chuàng)建邏輯,本節(jié)暫不深入 - 緩存中獲取不到目標(biāo)對象,則調(diào)用父類重載方法
DefaultSingletonBeanRegistry#getSingleton()
走創(chuàng)建對象邏輯。調(diào)用該方法時(shí)會將 Lambda 表達(dá)式作為ObjectFactory
的函數(shù)式接口實(shí)現(xiàn)傳入,用于觸發(fā)對象創(chuàng)建 - 調(diào)用
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; }
- 首先調(diào)用父類
-
DefaultSingletonBeanRegistry#getSingleton()
方法核心邏輯簡練,關(guān)鍵點(diǎn)如下:- 首先給第一級緩存加鎖防止并發(fā)問題,然后檢查第一級緩存中沒有目標(biāo)對象才開始創(chuàng)建
- 創(chuàng)建對象的步驟并不復(fù)雜,首先調(diào)用
DefaultSingletonBeanRegistry#beforeSingletonCreation()
方法標(biāo)記目標(biāo)對象正在創(chuàng)建中,然后調(diào)用傳入的函數(shù)式實(shí)現(xiàn)ObjectFactory#getObject()
開始創(chuàng)建對象,創(chuàng)建對象完成后調(diào)用DefaultSingletonBeanRegistry#afterSingletonCreation()
方法移除目標(biāo)對象的創(chuàng)建中標(biāo)記 - 最后調(diào)用
DefaultSingletonBeanRegistry#addSingleton()
方法將創(chuàng)建完成的新對象移入第一級緩存中,并將其從其他緩存中移除
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; } }
-
ObjectFactory#getObject()
的實(shí)現(xiàn)在 本節(jié)步驟1 中已經(jīng)提及,實(shí)際上最終將調(diào)用到AbstractAutowireCapableBeanFactory#createBean()
方法,該方法的核心邏輯是調(diào)用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); } }
-
AbstractAutowireCapableBeanFactory#doCreateBean()
方法并不復(fù)雜,核心要點(diǎn)如下:- 首先調(diào)用
AbstractAutowireCapableBeanFactory#createBeanInstance()
方法使用反射創(chuàng)建目標(biāo)類的空白對象 - 然后調(diào)用
DefaultSingletonBeanRegistry#addSingletonFactory()
方法將獲取 當(dāng)前對象的對象工廠存入第三級緩存 - 接著調(diào)用
AbstractAutowireCapableBeanFactory#populateBean()
方法填充空白對象的屬性 - 繼續(xù)調(diào)用
AbstractAutowireCapableBeanFactory#initializeBean()
方法對目標(biāo)對象做增強(qiáng)處理,包括使用切面創(chuàng)建代理對象等 - 最后調(diào)用
DefaultSingletonBeanRegistry#getSingleton()
方法從三級緩存中獲取的對象,接著校驗(yàn)經(jīng)過一系列處理后的對象和原始對象是否一致,一致則使用緩存中的對象替換掉原始對象,不一致則說明容器中存在存在多個(gè)目標(biāo)實(shí)例需要拋出異常
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; }
- 首先調(diào)用
-
AbstractAutowireCapableBeanFactory#populateBean()
方法會處理對象內(nèi)部的屬性依賴,核心處理分為以下幾步:- 首先調(diào)用
RootBeanDefinition#getPropertyValues()
直接從 Bean 定義封裝對象中獲取目標(biāo)對象的所有屬性 - 然后從容器中獲取所有后置處理器,使用特定后置處理器
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); } }
- 首先調(diào)用
-
AutowiredAnnotationBeanPostProcessor#postProcessProperties()
方法會處理@Autowired/@Value/@Inject
標(biāo)注的屬性,核心處理如下:- 調(diào)用
AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata()
方法將類中被@Autowired/@Value/@Inject
標(biāo)注的屬性字段和方法找出來,并將其封裝為對應(yīng)的結(jié)構(gòu),例如屬性字段對應(yīng)AutowiredFieldElement
- 調(diào)用
InjectionMetadata#inject()
方法開始進(jìn)行依賴的注入
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; }
- 調(diào)用
-
對于字段注入,最終將調(diào)用到
AutowiredAnnotationBeanPostProcessor#AutowiredFieldElement#inject()
方法執(zhí)行注入邏輯,關(guān)鍵步驟如下:- 首先調(diào)用
DefaultListableBeanFactory#resolveDependency()
通過對象工廠處理依賴,最終會調(diào)用到DefaultListableBeanFactory#getBean()
方法獲取依賴的對象。如果當(dāng)前存在A->B->A
循環(huán)依賴,則創(chuàng)建 B 對象的流程為 本節(jié)步驟1-7 的重復(fù),最終將調(diào)用DefaultListableBeanFactory#getBean()
方法去獲取創(chuàng)建中的 A 對象
,這部分下節(jié)繼續(xù)分析 - 獲取到依賴對象后,通過反射將其注入到指定字段
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); } }
- 首先調(diào)用
2.2 三級緩存的處理
-
在上一節(jié)步驟1中,筆者提到從容器中獲取對象時(shí)首先是從緩存中獲取,則對于創(chuàng)建中的對象 A ,首先將調(diào)用
DefaultSingletonBeanRegistry#getSingleton()
方法從內(nèi)部三級緩存中獲取實(shí)例,需要注意的點(diǎn)如下:- 首先從第一級緩存
singletonObjects
中獲取已經(jīng)創(chuàng)建完成的單例對象 - 如果第一級緩存中獲取不到,判斷當(dāng)前要獲取的對象是否在創(chuàng)建中,如是則從第二級緩存
earlySingletonObjects
中獲取 - 如果第二級緩存中獲取不到,判斷是否允許使用提前暴露的引用來獲取對象,如是則從第三級緩存
singletonFactories
中獲取到對象工廠,調(diào)用對象工廠方法獲取對象。獲取到對象后,將其存入第二級緩存,并將對象工廠從第三級緩存中移除
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; }
- 首先從第一級緩存
-
在 上一節(jié)步驟4 筆者提到第三級緩存實(shí)際是存放到對象工廠,通過對象工廠的函數(shù)式接口來實(shí)現(xiàn)獲取對象,則此處將觸發(fā)
AbstractAutowireCapableBeanFactory#getEarlyBeanReference()
方法執(zhí)行??梢钥吹竭@里的核心處理是遍歷SmartInstantiationAwareBeanPostProcessor
后置處理器對目標(biāo)對象進(jìn)行處理,在此過程中AnnotationAwareAspectJAutoProxyCreator#getEarlyBeanReference()
方法將被調(diào)用,最終執(zhí)行了其父類實(shí)現(xiàn)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; }
-
AbstractAutoProxyCreator#getEarlyBeanReference()
方法的關(guān)鍵處理分為兩步:- 首先生成該對象的緩存 key,并將原始對象存入內(nèi)部
earlyProxyReferences
緩存中,需注意該緩存是為了避免重復(fù)創(chuàng)建目標(biāo)對象的代理對象 - 調(diào)用
AbstractAutoProxyCreator#wrapIfNecessary()
方法搜索查找需要應(yīng)用在目標(biāo)對象上的增強(qiáng)切面,找到后就通過動(dòng)態(tài)代理創(chuàng)建代理對象
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; }
- 首先生成該對象的緩存 key,并將原始對象存入內(nèi)部
-
以上方法執(zhí)行完畢,B 對象創(chuàng)建完成,回到最初創(chuàng)建對象 A 的流程中。此時(shí)對象 A 的屬性填充完成,開始執(zhí)行
AbstractAutowireCapableBeanFactory#initializeBean()
對目標(biāo)對象執(zhí)行增強(qiáng)處理,此處的核心如下:- 首先調(diào)用
AbstractAutowireCapableBeanFactory#invokeAwareMethods()
方法執(zhí)行目標(biāo)對象的相關(guān)自省方法,填充特定屬性 - 調(diào)用
AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization()
方法遍歷后置處理器列表,執(zhí)行處理器BeanPostProcessor#postProcessBeforeInitialization()
方法對目標(biāo)對象執(zhí)行實(shí)例化前的增強(qiáng) - 調(diào)用
AbstractAutowireCapableBeanFactory#invokeInitMethods()
方法判斷目標(biāo)對象是否實(shí)現(xiàn)了 InitializingBean 接口,是則執(zhí)行對應(yīng)接口方法 - 調(diào)用
AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization()
方法遍歷后置處理器列表,執(zhí)行處理器BeanPostProcessor#postProcessAfterInitialization()
方法對目標(biāo)對象執(zhí)行實(shí)例化后的增強(qiáng),這一步將觸發(fā)AbstractAutoProxyCreator#postProcessAfterInitialization()
方法為目標(biāo)對象創(chuàng)建代理
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; }
- 首先調(diào)用
-
AbstractAutoProxyCreator#postProcessAfterInitialization()
方法的處理如下,可以看到這部分基本與 本節(jié)步驟3 的邏輯相呼應(yīng),如果earlyProxyReferences
緩存中存在目標(biāo)對象標(biāo)記,則證明已經(jīng)為目標(biāo)對象創(chuàng)建過代理對象了,不需要再重新創(chuàng)建,從而避免多個(gè)代理對象存在造成的不一致問題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; }
3. 遺留問題
從源碼分析中可以看到,三級緩存解決循環(huán)依賴中的動(dòng)態(tài)代理問題主要依賴 AbstractAutoProxyCreator#earlyProxyReferences
緩存。但是需注意,當(dāng)存在特殊的 BeanPostProcessor 對目標(biāo)對象額外進(jìn)行代理增強(qiáng)時(shí),AbstractAutoProxyCreator#earlyProxyReferences
緩存標(biāo)記就失效了,此時(shí)依然會產(chǎn)生循環(huán)依賴異常文章來源:http://www.zghlxwxcb.cn/news/detail-500593.html
例如 A->B->A 循環(huán)依賴中,如果 A 被
@Async
注解并通過@EnableAsync
開啟了異步特性,則必將拋出循環(huán)依賴異常文章來源地址http://www.zghlxwxcb.cn/news/detail-500593.html
到了這里,關(guān)于SpringBoot 三級緩存解決循環(huán)依賴源碼分析的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!