为什么会出现循环依赖问题?
(前提知识点:Bean的生命周期会有四个阶段,包括实例化、属性赋值、初始化和销毁)而在spring容器主函数调用的时候会扫描class文件生成BeanDefinition对象,然后创建单例bean存储到单例池中,这时会调用createBean()方法,而createBean()中真正创建实例的是doCreateBean()方法,doCreateBean()方法包括了Bean生命周期中的实例化、属性赋值、初始化逻辑。在执行到属性赋值populateBean()
时会进行依赖注入操作,如果属性有@Autowired注解修饰,则会调用getBean()方法在单例池中查找对应的Bean实例,如果没有则会执行createBean()创建属性类的实例。这时下列场景就会出现问题。
服务A注入服务B:调用createBean()创建A实例,创建A实例时调用A的populateBean()会getBean(),然后调用createBean()创建B实例。
服务B注入服务A:调用createBean()创建B实例,创建A实例时调用A的populateBean()会getBean(),然后调用createBean()创建B实例。
这就是循环依赖问题。
如何判断是否出现了循环依赖?
spring会维护一个singletonsCurrentlyInCreation的Set结构,这个Set用来存储单例的beanName。通过判断在singletonsCurrentlyInCreation中是否存在当前beanName的元素即可判断是否触发了循环依赖。
这个Set结构有三个关键函数:
// DefaultSingletonBeanRegistry.class
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
- isSingletonCurrentlyInCreation()用来判断是否触发了循环依赖。
- beforeSingletonCreation()在创建单例bean之前调用,作用是将当前bean的beanName加入到Set中(判断是否循环依赖的前提)。
- afterSingletonCreation()在创建单例bean之后调用,将beanName从Set中删除。
Spring在出现循环依赖时代码的执行流程
在阐述流程钱我们先将提一下循环依赖中的三级缓存机制:
- singletonObjects(一级缓存)。单例池,用来存储走完完整Bean创建流程的Bean普通对象或者Bean代理对象。
- earlySingletonObjects(二级缓存)。用来存储经过AOP后的动态反射对象。
- singleFactories(三级缓存)。用来存储基于bean对象的拉姆达表达式。
首先spring容器(applicationContext)在系统启动后会做这么两件事情:
- 扫描项目输出目录中的class文件,包装成DefinitionBean数据结构放在一个map中。
- 遍历所有作用域为单例的bean对象,创建单例池。
而在单例创建过程中我们假设会先创建AService单例。
创建AService单例
创建AService单例时会调用getBean(beanName)方法获取单例bean,getBean()多个重载方法都是通过调用doGetBean()方法实现。
// AbstractBeanFactory.class
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
String beanName = this.transformedBeanName(name);
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if (sharedInstance != null && args == null) {
...
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
...
try {
RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
...
// 判断是否是单例
if (mbd.isSingleton()) {
// 获取单例
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
...
} else {
...
}
} catch (BeansException var26) {
this.cleanupAfterBeanCreationFailure(beanName);
throw var26;
}
}
if (requiredType != null && !requiredType.isInstance(bean)) {
...
} else {
return bean;
}
}
先看看this.getSingleton(beanName)的返回结果:
// DefaultSingletonBeanRegistry.class
// 当允许循环依赖(allowEarlyReeference)时,会有三种可能性
// 1. 当一级缓存二级缓存中都没有对应bean,且没有触发循环依赖(即this.isSingletonCurrentlyInCreation),则返回null
// 2. 当一级缓存二级缓存中都没有对应bean,但是触发了循环依赖时,当三级缓存不为空时,则基于三级缓存的拉姆达表达式生成对应代理对象并放到二级缓存中,并删除三级缓存中对应的项(这里使用了双重检查锁)。
// 3. 当一级缓存中存在对应的bean,则返回一级缓存
// 4. 当二级缓存中存在对应的bean,则返回二级缓存
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized(this.singletonObjects) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
因为这是没有任何缓存数据和辅助标记数据(isSingletonCurrentlyInCreation),this.getSingleton(beanName)返回null。
因为是单例池创建,会执行this.getSingleton(beanName, singletonFactory):
// DefaultSingletonBeanRegistry.class
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) {
...
// 将当前beanName加入到singletonsCurrentlyInCreation的Set中,是判断循环依赖的前提
this.beforeSingletonCreation(beanName);
...
try {
singletonObject = singletonFactory.getObject();
...
} catch (IllegalStateException var16) {
...
} catch (BeanCreationException var17) {
...
} finally {
...
// 将当前beanName从singletonsCurrentlyInCreation删除
this.afterSingletonCreation(beanName);
}
if (newSingleton) {
this.addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
入参的singletonFactory实则是一个拉姆达表达式:
() -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
}
表达式内会调用createBean(beanName, mad, args)方法,而createBean方法的核心则是我们熟知的doCreateBean(beanName, mbdToUse, args)方法(该方法中包括了bean生命周期的三个阶段,即实例化、属性赋值和初始化):
// AbstractAutowireCapableBeanFactory.class
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
// 实例化
if (instanceWrapper == null) {
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
...
// 判断是否是正在创建的单例Bean
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
...
// 添加到三级缓存
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
Object exposedObject = bean;
try {
// 属性赋值
this.populateBean(beanName, mbd, instanceWrapper);
// 初始化
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
} catch (Throwable var18) {
if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
throw (BeanCreationException)var18;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}
...
}
因为在this.getSingleton(beanName, singletonFactory)中我们调用了this.beforeSingletonCreation(beanName)方法,earlySingletonExposure值为true,所以会添加当前bean的三级缓存。
前面都是铺垫,循环依赖问题发生时机就是属性赋值实现依赖注入时,所以我们要对this.populateBean(beanName, mbd, instanceWrapper)一探究尽:
// AbstractAutowireCapableBeanFactory.class
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
...
} else {
...
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == 1 || resolvedAutowireMode == 2) {
...
if (resolvedAutowireMode == 1) {
this.autowireByName(beanName, mbd, bw, newPvs);
}
if (resolvedAutowireMode == 2) {
this.autowireByType(beanName, mbd, bw, newPvs);
}
...
}
...
}
}
重点关注依赖注入方法this.autowireByName(beanName, mbd, bw, newPvs):
// AbstractAutowireCapableBeanFactory.class
protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
String[] propertyNames = this.unsatisfiedNonSimpleProperties(mbd, bw);
String[] var6 = propertyNames;
int var7 = propertyNames.length;
for(int var8 = 0; var8 < var7; ++var8) {
String propertyName = var6[var8];
if (this.containsBean(propertyName)) {
// 获取bean实例
Object bean = this.getBean(propertyName);
pvs.add(propertyName, bean);
this.registerDependentBean(propertyName, beanName);
...
} else if (this.logger.isTraceEnabled()) {
...
}
}
}
这里会遍历bean中被被@Autowired修饰的属性,如果在BeanDefinitionMap中有对应的bean数据,则会调用getBean(propertyName)方法获取bean实例,这时细心的同学就会发现这不就是创建AService单例时最初调用的函数吗?看来我们来到了进入下一个循环的节点——创建BService单例(其实AService单例的创建过程并没有走完,但作为循环依赖的一个关键节点,我们会在后面的小节说明AService单例创建的后续操作)。
创建BService单例
…
转眼间我们就到创建BService单例的属性赋值过程中this.autowireByName(beanName, mbd, bw, newPvs)方法(前面的过程跟创建AService单例如出一辙),这里我们又再次拿到AService的beanName去调用this.getBean(beanName)方法,但这次执行的结果会大不相同。
重走西游,用AService的beanName再次调用getBean(beanName)方法
如上文所述,getBean()底层调用了doGetBean(),让我们看看这次执行的哪一个分支逻辑:
// AbstractBeanFactory.class
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
String beanName = this.transformedBeanName(name);
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if (sharedInstance != null && args == null) {
...
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
...
try {
RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
...
// 判断是否是单例
if (mbd.isSingleton()) {
// 获取单例
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
...
} else {
...
}
} catch (BeansException var26) {
this.cleanupAfterBeanCreationFailure(beanName);
throw var26;
}
}
if (requiredType != null && !requiredType.isInstance(bean)) {
...
} else {
return bean;
}
}
会看上面对this.getSingleton(beanName)的分析,这次会走第二条分支逻辑,会返回AService的Bean代理对象(即二级缓存,且这时只有二级缓存中能查到对应的元素),这里就不会走createBean()流程而是直接返回bean的代理对象了,到这里我们发现其实循环依赖已经被解决了,但是创建AService单例的创建过程其实还没有执行完,我们继续往后看二级缓存中的对象是如何过渡到一级缓存中(单例池)的。
九九归一,完整单例创建的后续操作
本例中BService其实只是作为复现循环依赖场景的一个工具人,所有过程和AService单例创建相同,所以我们跳过它的执行过程,直接快进到最外层(即AService)的createBean(beanName, mad, args)返回这行代码(这里属性赋值和初始化已经执行完):
// DefaultSingletonBeanRegistry.class
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) {
...
// 将当前beanName加入到singletonsCurrentlyInCreation的Set中,是判断循环依赖的前提
this.beforeSingletonCreation(beanName);
...
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (IllegalStateException var16) {
...
} catch (BeanCreationException var17) {
...
} finally {
...
// 将当前beanName从singletonsCurrentlyInCreation删除
this.afterSingletonCreation(beanName);
}
if (newSingleton) {
this.addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
createBean()方法作为拉姆达表达式的一部分,singletonFactory.getObject()返回的实际就是createBean()方法的返回值,即二级缓存。
因为AService实例创建基本结束,这里调用this.afterSingletonCreation(beanName)将beanName从singletonCurrentlyInCreation中删除。
最后看看this.addSingleton(beanName, singletonObject)干了什么:
// DefaultSingletonBeanRegistry.class
protected void addSingleton(String beanName, Object singletonObject) {
synchronized(this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
...
}
}
没错,如预料一样无趣,就是将二级缓存中的bean实例放到一级缓存(单例池)中,然后将其从二级缓存和三级缓存中删除。至此循环依赖场景下Spring的执行完整过程就讲解完毕。后面我们浅析一下各个数据结构的作用。
spring如何解决循环依赖的?
常说的循环依赖如何形成的(假设没有二级缓存和三级缓存及相关逻辑)?
- 创建A的bean实例(getBean()调用doGetBean(),doGetBean()里面会调用createBean()方法),createBean()会执行实例化、属性赋值、初始化,在属性赋值时会进行依赖注入,此时会创建B的bean实例。
- B单例创建时依然会执行B的createBean()方法,然后在b的属性赋值时,会调用getBean(beanName)方法获取A实例。
- 再次通过getBean(beanName)方法获取A实例,这时如果只有一级缓存,因为最外层A的实例创建过程没有执行完,所以从一级缓存中并找不到bean对象,会再次执行A实例的创建操作,从而形成死循环。
只有一级缓存,并不能知道这个Bean到底创建过没有。
两级缓存能解决循环依赖吗(没有第二级缓存及相关逻辑)?
不行,如果有多个bean与一个bean形成了循环依赖,例如A与B形成了循环依赖的同时也与C形成了循环依赖。这时B与C在属性赋值时会同时调用getBean()方法获取单例,因为没有第二级缓存,无法判断是否已经创建过代理对象,所以两者都会重新生成一个bean的代理对象,这样就破坏了单例作用域。
各数据结构的作用
- singletonObjects(一级缓存,即单例池)。存储完整走完Bean生命周期的bean单例对象。
- earlySingletonObjects(二级缓存)。存储还未完全走完Bean生命周期的代理对象。用来判断是否存在已经创建的代理对象实例,和获取已经创建的代理对象实例。
- singleFactories(三级缓存)。存储带有beanName和普通bean信息的拉姆达表达式,作为一个bean已经存在实例的依据,用来打破循环。用来判断是否存在已经创建的普通bean实例,和获取已经创建的普通bean实例。
- singletonsCurrentlyInCreation(用来判断bean是否在创建过程中)。
触发循环依赖时会发生AOP提前
当出现循环依赖时,会将在初始化过程中的AOP处理过程提前到属性赋值之前实例化之后,看看Spring是如何实现的。
接口设计及实现
先来看看AOP实现类及其接口设计:
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {...}
实现了SmartInstantiationAwareBeanPostProcessor接口,这是将需要提前获取的这种行为作为规范抽象成了接口:
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
@Nullable
default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
@Nullable
default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
return bean;
}
}
我们重点关注下getEarlyBeanReference(Object bean, String beanName)方法就行。
当然,这个接口的父接口是经典的后置处理器:
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {...}
所以需要实现这两个方法:
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
所以需要实现这俩方法。
说了这么多,其实最主要的方法就只有几个:
// AbstractAutoProxyCreator.class
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
...
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
...
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) {
if (StringUtils.hasLength(beanName)) {
return FactoryBean.class.isAssignableFrom(beanClass) ? "&" + beanName : beanName;
} else {
return beanClass;
}
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
...
}
- getEarlyBeanReference(Object bean, String beanName)。AOP提前时调用的就是这个方法,内部实现和postProcessAfterInitialization(@Nullable Object bean, String beanName)类似。
- postProcessAfterInitialization(@Nullable Object bean, String beanName)。当不出现循环依赖时执行AOP的方法。当出现循环依赖时,因为之前缓存过当前bean,所以会跳过。
- wrapIfNecessary(Object bean, String beanName, Object cacheKey)。AOP实现逻辑在这个方法中实现。
现在我们只需要getEarlyBeanReference和getEarlyBeanReference方法的调用时机就能搞懂Spring是如何将AOP提前的了。
AOP提前的实现流程
这里我们基于循环依赖中执行流程的场景事例来模拟AOP的实现过程。
首先在创建AService单例时,基于调用链getBean()->doGetBean()->createBean()->doCreateBean(),快进到这:
// AbstractAutowireCapableBeanFactory.class
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
// 实例化
if (instanceWrapper == null) {
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
...
// 判断是否是正在创建的单例Bean
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
...
// 添加到三级缓存
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
Object exposedObject = bean;
try {
// 属性赋值
this.populateBean(beanName, mbd, instanceWrapper);
// 初始化
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
} catch (Throwable var18) {
if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
throw (BeanCreationException)var18;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}
...
}
在三级缓存中添加了AbstractAutowireCapableBeanFactory类getEarlyBeanReference(Object bean, String beanName)方法的具体实现,我们看看具体实现:
// AbstractAutowireCapableBeanFactory.class
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Iterator var5 = this.getBeanPostProcessors().iterator();
while(var5.hasNext()) {
BeanPostProcessor bp = (BeanPostProcessor)var5.next();
// 实现了AOP提前
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor)bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
这里遍历了所有SmartInstantiationAwareBeanPostProcessor接口的实例并调用了getEarlyBeanReference(exposedObject, beanName)方法,这下我们知道了AOP提前操作是在哪行代码实现的。
但是三级缓存中保存的是拉姆达表达式,实际上添加缓存时并没有执行,这时就有两种情况,如果没有循环依赖,那就一直不会执行,如果存在循环依赖,则在触发循环依赖的瞬间才会执行AOP,即创建BService单例时的getBean(BService)->doGetBean()->createBean()->doCreateBean()->populateBean()->getBean(AService)->doGetBean()->getSingleton()
// DefaultSingletonBeanRegistry.class
// 当允许循环依赖(allowEarlyReeference)时,会有三种可能性
// 1. 当一级缓存二级缓存中都没有对应bean,且没有触发循环依赖(即this.isSingletonCurrentlyInCreation),则返回null
// 2. 当一级缓存二级缓存中都没有对应bean,但是触发了循环依赖时,当三级缓存不为空时,则基于三级缓存的拉姆达表达式生成对应代理对象并放到二级缓存中,并删除三级缓存中对应的项(这里使用了双重检查锁)。
// 3. 当一级缓存中存在对应的bean,则返回一级缓存
// 4. 当二级缓存中存在对应的bean,则返回二级缓存
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized(this.singletonObjects) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 基于拉姆达表达式生成二级缓存
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
执行到singletonFactory.getObject()代码时,才会真正执行AOP操作并返回代理对象。在BService做属性赋值的依赖注入时会直接将AService的代理对象返回。
最后我们看看在创建AService实例的初始化阶段(getBean()->doGetBean()->createBean()->doCreateBean()->initializeBean())是如何跳过AOP的。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
this.invokeAwareMethods(beanName, bean);
return null;
}, this.getAccessControlContext());
} else {
this.invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
// 初始化后的扩展
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)这个方法实现了AOP操作:
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Object current;
for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
BeanPostProcessor processor = (BeanPostProcessor)var4.next();
current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
}
return result;
}
这里会调用AOP实现类AbstractAutoProxyCreator的postProcessAfterInitialization方法(前面有分析过),所以这里会直接返回代理对象。至此AOP提前的代码原理已经全部解析完毕。
总结
- 三级缓存及作用。
- singletonObjects(一级缓存)。用来存储完整走完Bean生命周期中实例化、属性赋值和初始化三个阶段的单例。一级缓存主要用来缓存单例对象,spring基于它实现了单例模式。
- earlySingletonObjects(二级缓存)。用来存储还未完全走完Bean生命周期的Bean对象(可能是普通Bean或普通Bean的代理对象)。二级缓存为了保证Bean对象的单例特性,因为最终创建的单例可能是普通Bean对象也可能是普通Bean的代理对象。
- singleFactories(三级缓存)。用来存储基于bean的拉姆达表达式。
- 通过缓存和逻辑判断解决了循环依赖问题。
- 三级缓存的优势。
- 使bean创建时的逻辑更清晰。
- 二级三级缓存的存在使加锁粒度更小,提高了并发性能。
- 第三级缓存存储的拉姆达表达式,具有更高的灵活性。
Comments (1)
Bean的生命周期 – spice and wolfsays:
2024年 9月 15日 at 上午10:08[…] 在这个方法中会根据三级缓存机制拿到缓存的bean,如果都没有则会执行bean的创建流程,即执行createBean()方法,createBean()的核心逻辑都在doCreateBean()方法中,所以我们想要了解bean的生命周期需要集中学习这个代码的执行逻辑。 […]