Bean的屬性裝配前2:SmartInstantiationAwareBeanPostProcessor

接上文

掃描完Bean的需要自動注入的屬性信息之后,接著回來doCreateBean,代碼走到getEarlyBeanReference

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, 
            final @Nullable Object[] args) throws BeanCreationException {
    // ...

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    // 官方注釋說明這里采取緩存的方式來處理Bean的循環(huán)引用
    boolean earlySingletonExposure 
            = (mbd.isSingleton() && this.allowCircularReferences 
                                 && isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isDebugEnabled()) {
            logger.debug("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // ...
}

/**
 * Add the given singleton factory for building the specified singleton
 * if necessary.
 * <p>To be called for eager registration of singletons, e.g. to be able to
 * resolve circular references.
 * 將一個ObjectFactory緩存到三級緩存singletonFactories
 * @param beanName the name of the bean
 * @param singletonFactory the factory for the singleton object
 */
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(singletonFactory, "Singleton factory must not be null");
    synchronized (this.singletonObjects) {
        if (!this.singletonObjects.containsKey(beanName)) {
            this.singletonFactories.put(beanName, singletonFactory);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
}

/**
 * Obtain a reference for early access to the specified bean,
 * typically for the purpose of resolving a circular reference.
 * 嘗試從Bean緩存中獲取提前暴露出來的其他Bean,避免循環(huán)依賴的情況
 * @param beanName the name of the bean (for error handling purposes)
 * @param mbd the merged bean definition for the bean
 * @param bean the raw bean instance
 * @return the object to expose as bean reference
 */
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;
}

這個方法主要還是配合Spring處理兩個Bean之間的循環(huán)引用使用的,Spring將正在創(chuàng)建的Bean經(jīng)過這個方法的處理之后,緩存到第三級緩存singletonFactories


擴展:以AspectJAwareAdvisorAutoProxyCreator為例,簡述SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference的應用

前文Bean實例化1中,介紹了AspectJAwareAdvisorAutoProxyCreator通過繼承AbstractAutoProxyCreator實現(xiàn)了SmartInstantiationAwareBeanPostProcessor接口,在InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation方法中緩存了不需要創(chuàng)建代理的對象,當執(zhí)行SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference方法的時候,會根據(jù)之前緩存的信息,決定是否需要返回當前Bean的代理對象

public abstract class AbstractAutoProxyCreator 
        extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    
    @Override
    public Object getEarlyBeanReference(Object bean, String beanName) 
                throws BeansException {

        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            this.earlyProxyReferences.add(cacheKey);
        }
        return wrapIfNecessary(bean, beanName, cacheKey);
    }

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        // 校驗當前Bean是否需要生成代理對象
        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.
        // 創(chuàng)建代理對象
        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;
    }
}

因此SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference主要還是為了解決創(chuàng)建Bean的過程中,避免產(chǎn)生循環(huán)依賴的問題,緩存當前的Bean(可以是Bean,也可以是Bean的代理對象)到三級緩存中,假設產(chǎn)生了循環(huán)依賴,相互依賴的Bean可以從三級緩存中獲取到當前創(chuàng)建到一半的Bean進行屬性裝配

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容