扫描完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进行属性装配