一、前言
Spring循环依赖
是面试考点之一。面试官可以深挖面试者对Spring
关于Bean的生命周期
掌握情况。Spring循环依赖
也是Spring
难点之一,逻辑比较绕,需要对Spring Bean
的生命周期了如指掌。
@Component
public class A {
@Autowired
B b;
}
@Component
public class B {
@Autowired
A a;
}
A 生命周期
1. class文件
2. 通过beanName去缓存中获取对象。一开始,单例池没有,且a也没有处于正在创建集合中,所以不会去二级缓存、三级缓存拿对象,相关代码[标记①]
3. 把对象放到正在创建集合中(beforeSingletonCreation(beanName);) 相关代码[标记②]
4. 通过反射实例化对象(createBeanInstance();) 相关代码[标记③]
5. 添加对象工厂到二级缓存中 相关代码[标记④]
6. 属性填充。在这里发现需要B对象,从单例池获取B->null->且b也没有处于正在创建集合中->实例化B且完成B的生命周期 相关代码[标记⑤]
wait for b init...
7. 初始化 相关代码[标记⑥]
8. 从二级缓存中获取Bean 相关代码[标记⑦]
9. 添加到单例池 相关代码[标记⑥]
B 生命周期
1. class文件
2. 通过beanName去缓存中获取对象。一开始,单例池没有,且a也没有处于正在创建集合中,所以不会去二级缓存、三级缓存拿
3. 把对象放到正在创建集合中(beforeSingletonCreation(beanName);)
(singletonObject = singletonFactory.getObject();)
4. 通过反射实例化对象(createBeanInstance();)
5. 添加对象工厂到二级缓存中
6. 属性填充。在这里发现需要A对象,从单例池获取A->null->此时a在正在创建集合中->从三级缓存中获取对象(如果a存在切面,则返回代理对象),将对象放至二级缓存,删除三级缓存
7. 初始化
8. 从二级缓存中获取Bean
9. 添加到单例池
singletonObjects
。存储已走完Spring
生命周期的Bean
。注意,对象
和Bean
在Spring的世界是完全两个概念。通过反射实例化的叫对象,此时这个对象并未完成Spring
的生命周期流程(如后置处理器等),Bean
则表示已经完成Spring
整个生命周期流程。earlySingletonObjects
。存储已实例化(通过反射创建的对象)但是未走完Spring
生命周期流程的对象。singletonFactories
。存储对象工厂
。目的是在适当的时候通过对象工厂生成AOP
代理对象。AOP
代理。对象工厂清楚如何创建对象的AOP代理,但是不会立马创建,而是到合适的时机进行AOP
代理对象的创建。二级缓存存
在的目的之一是保证对象只有一次AOP
代理。当调用三级缓存的getObject()
方法返回的对象会存入二级缓存,这样,当接下来的依赖者调用的时候, 会先判断二级缓存
是否有目标对象,如果存在直接返回。// DefaultSingletonBeanRegistry#getSingleton
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从一级缓存中获取bean,即单例池
Object singletonObject = this.singletonObjects.get(beanName);
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);
}
}
}
}
return singletonObject;
}
// DefaultSingletonBeanRegistry#beforeSingletonCreation
protected void beforeSingletonCreation(String beanName) {
// 1.inCreationCheckExclusions: 判断当前对象是否存在 [被剔除] 集合对象中 注解 excludeFilters=xx
// 2.singletonsCurrentlyInCreation: 将当前对象添加 [正在创建单例Bean] 集合中
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
// AbstractAutowireCapableBeanFactory#createBeanInstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 如果为自动装配,则推断出来各种候选的构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 利用推断出来的修行构造方法去实例化对象。如果使用构造器注入,这里直接返回
return autowireConstructor(beanName, mbd, ctors, args);
}
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
// 利用推断出来的候选构造方法去实例化对象
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
// 如果没有推断出合适的构造方法(或者没有提供特殊的构造方法),则使用默认的构造方法
return instantiateBean(beanName, mbd);
}
// DefaultSingletonBeanRegistry#addSingletonFactory
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);
}
}
}
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
// 这里会有三个后置处理器,分别是:
// 1、ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
// 2、AutowiredAnnotationBeanPostProcessor
// 3、CommonAnnotationBeanPostProcessor
// AutowiredAnnotationBeanPostProcessor: 解析@Autowire属性注入
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 属性自动注入主要使用 AutowiredAnnotationBeanPostProcessor后置处理器
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 4-1、执行Aware (BeanNameAware、BeanClassLoaderAware 、BeanFactoryAware)
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 4.2 初始化前
// △△ 执行Bean后置处理器(lifeCycle Callback)
// 重写这个方法[postProcessBeforeInitialization]则会在这里被调用
// lifeCycle callback init by annotation
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 4.3、初始化 [InitializingBean]
// lifeCycle callback init by interface.
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 4.4、初始化后
// 完成AOP,生成动态代理; 事件发布; 监听
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
// AbstractAutowireCapableBeanFactory#doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
if (earlySingletonExposure) {
// 在解决循环依赖时,获取beanName从二级缓存中获取
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
...
}
}
...
// DefaultSingletonBeanRegistry#getSingleton
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 把当前对象放到 [正在创建] 的集合(singletonsCurrentlyInCreation)当中
beforeSingletonCreation(beanName);
// getObject方法会调用AbstractAutowireCapableBeanFactory的createBean方法
singletonObject = singletonFactory.getObject();
//添加到单例池
addSingleton(beanName, singletonObject);
}
}
依赖注入方式 | 循环依赖能否被解决 |
---|---|
均采用setter方法注入 | 能 |
均采用构造器注入 | 不能 |
A中注入B的方式为setter方法,B中注入A的方式为构造器 | 能 |
A中注入B的方式为构造器,B中注入A的方式为setter方法 | 不能 |
注:
A
先创建。小结:
- 主对象(具备循环依赖且最先加载的类,简称A)不能通过
构造函数
的方法注入所依赖的Bean对象(简称B),而B不受限制,可以使用任意方式注入(setter、@Autowire、构造函数)
。- 循环依赖中A对象不能使用
构造函数
注入的原因是在AbstractAutowireCapableBeanFactory#createBeanInstance
方法中做类型推断时,如果推断是以构造方法实例B,则会直接调用``AbstractAutowireCapableBeanFactory#autowireConstructor,该方法会通过调用
AbstractAutowireCapableBeanFactory#doCreateBean创建对象,但是由于A对象没有提前暴露工厂(不给机会呀),所以只能一步步创建,但是走到代码
DefaultSingletonBeanRegistry#getSingleton的
beforeSingletonCreation方法时,由于此时A正在创建集合,强行添加则会返回
false`,则抛出异常。相关代码③
如果解决循环依赖呢?
setter
注入Spring
团队建议我们使用constructor based (构造注入)
的方式管理我们的依赖,对强制依赖使用断言。这里推荐使用setter
注入。Spring
通过三级缓存
解决了循环依赖。其他一级缓存为单例池,二级缓存为早期曝光对象,三级缓存为早期曝光对象工厂。当A、B两类发生循环引用,在A实例化之后,将自己提早曝光(即加入三级缓存),如果A初始AOP
代理,该工厂对象返回的是被代理的对象,若未被代理,返回对象本身。当A进行属性注入时,经过之前实例化步骤,此时轮到B属性注入,调用getBean(a)
获取A对象,由于A处理正在创建集合中,此时也发了循环依赖,所以可以从三级缓存获取对象工厂(如果A被AOP代理,此时返回就是代理对象),并把对象放到二级缓存中,这样保证A只经过一次AOP代理。接下来,B走完Spring
生命周期流程,并放入单例池中。当B创建完后,会将B注入A,A走完Spring
生命周期流程。到此,循环依赖结束。