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的循环引用
    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,避免循环依赖的情况
 * @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之间的循环引用使用的,Spring将正在创建的Bean经过这个方法的处理之后,缓存到第三级缓存singletonFactories


扩展:以AspectJAwareAdvisorAutoProxyCreator为例,简述SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference的应用

前文Bean实例化1中,介绍了AspectJAwareAdvisorAutoProxyCreator通过继承AbstractAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor接口,在InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation方法中缓存了不需要创建代理的对象,当执行SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference方法的时候,会根据之前缓存的信息,决定是否需要返回当前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.
        // 创建代理对象
        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主要还是为了解决创建Bean的过程中,避免产生循环依赖的问题,缓存当前的Bean(可以是Bean,也可以是Bean的代理对象)到三级缓存中,假设产生了循环依赖,相互依赖的Bean可以从三级缓存中获取到当前创建到一半的Bean进行属性装配

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。