问题描述
@Service
public GoodsService{
@Autowared
BillService billService
}
@Service
public BillService{
@Autowared
GoodsService goodsService
}
Spring bean大致的生命周期如下:
反射创建对象 -> 依赖注入 -> 初始化方法init -> aop等后置处理器 -> …
当执行GoodsService依赖注入时,该Service还未成为一个Spring bean(生命周期创建阶段还未完成),因此,无法将其注入BillService中(一个例子是,如果注入,则破坏了aop逻辑,因为此时的GoodsService还未配置aop代理,注入的是它本身)。
解决方案
三级缓存解决方案
获取bean流程
源码
doGetBean():获取bean
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// 第一次尝试获取单例bean
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
......
}
else {
......
// Create bean instance.
if (mbd.isSingleton()) {
// 第二次尝试获取单例bean
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
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);
}
......
}
return (T) bean;
}
getSingleton():获取单例对象,在第一次尝试获取单例bean时调用
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 尝试取一级缓存
Object singletonObject = this.singletonObjects.get(beanName);
// 如果该bean正在创建,isSingletonCurrentlyInCreation()为true,走如下分支
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);
}
}
}
}
// 如果还未创建,则返回null
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
doCreateBean() :创建bean,在第二次尝试获取单例bean时调用
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
......
// 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.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 加入三级缓存
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 依赖注入
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化方法
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);
}
}
// 这里检查是否提前暴露了bean
// 如果允许循环依赖,走下面分支
if (earlySingletonExposure) {
// 这里只会查一级缓存和二级缓存,一级缓存肯定为空,若存在循环依赖,则返回二级缓存的对象
Object earlySingletonReference = getSingleton(beanName, false);
// 如果二级缓存查到了对象,说明存在循环依赖,走下面分支
if (earlySingletonReference != null) {
// 如果此时二级缓存的对象与exposedObject相等,说明提前暴露的bean对象是安全的
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
// 否则,证明exposedObject被进行了其他代理(可能是init阶段),前面提前暴露时没有捕捉到,证明提前暴露是不安全的
// 如果还有依赖它的bean,说明bean有可能被暴露出去了,走下面分支
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
// 遍历所有依赖它的Bean
for (String dependentBean : dependentBeans) {
// 如果此时有依赖它的bean被成功创建了,证明bean真的被暴露出去了,抛出异常
// 原因是因为getEarlyBeanReference()方法不一定能处理所有的代理情形
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 " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
return exposedObject;
}
getEarlyBeanReference():三级缓存的实例获取实现方法:
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 获取后置处理器,提前完成aop等逻辑
// 注意,spring扩展点很多,此处可能不能处理所有扩展点中的代理逻辑
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
if (exposedObject == null) {
return null;
}
}
}
}
return exposedObject;
}
总结
使用三级缓存,各级缓存作用如下:
- 三级缓存(singletonFactories):将aop等后置处理器包装到工厂中
- 二级缓存(earlySingletonObjects):存放三级缓存中生成的对象,让三级缓存的对象生成方法只执行一次,保证对象是单例的
- 一级缓存(singletonObjects):存放所有已经初始化完成的bean,保证bean是单例的