前言
写完了Spring比较重要和复杂的大点,打算写一些更接近实际应用和面试问的比较多的小点,结合具体问题来看看Spring源码是怎么解决的,不过由于是小点,可能不能兼顾到整体的流程,希望大家通过之前的博文,对Spring已经有了一个整体的把控,对流程也相对比较清楚,然后结合具体问题,对一些具体的点进行更深入的研究。
那这篇博客就来看看Spring中比较有代表性的循环依赖问题,看看Spring是怎么解决的,Spring的很多设计和原理都可以应用到我们的实际工作中,技术需要落地,应用的过程也是一个加深理解的过程。
示例代码
配置类
@Configuration
@ComponentScan(value = "com.ambition")
public class AmbitionConfig {
}
A服务
@Component
public class AService {
@Autowired
private BService bService;
public AService() {
System.out.println("aService create");
}
public void print() {
System.out.println(bService);
}
}
B服务
@Component
public class BService {
@Autowired
private AService aService;
public BService() {
System.out.println("bService create");
}
public void print() {
System.out.println(aService);
}
}
测试类
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
context.register(AmbitionConfig.class);
AService aService = context.getBean(AService.class);
aService.print();
BService bService = context.getBean(BService.class);
bService.print();
}
打印结果
aService create
bService create
com.ambition.service.BService@19bb089b
com.ambition.service.AService@4563e9ab
大家都知道Spring能够解决循环依赖的问题,那么下面这个测试类呢:
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
context.register(AmbitionConfig.class);
AbstractAutowireCapableBeanFactory beanFactory =
(AbstractAutowireCapableBeanFactory) context.getBeanFactory();
// 关闭循环依赖
beanFactory.setAllowCircularReferences(Boolean.FALSE);
context.refresh();
AService aService = context.getBean(AService.class);
aService.print();
BService bService = context.getBean(BService.class);
bService.print();
}
打印结果
aService create
bService create
五月 11, 2020 8:20:45 下午 org.springframework.context.support.AbstractApplicationContext refresh
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'AService': Unsatisfied dependency expressed through field 'bService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'BService': Unsatisfied dependency expressed through field 'aService'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'AService': Requested bean is currently in creation: Is there an unresolvable circular reference?
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'AService': Unsatisfied dependency expressed through field 'bService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'BService': Unsatisfied dependency expressed through field 'aService'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'AService': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:609)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:116)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:367)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1682)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:666)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:526)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:344)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:342)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:159)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:874)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:1036)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:626)
at com.ambition.study.CircularReferenceTest.main(CircularReferenceTest.java:53)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'BService': Unsatisfied dependency expressed through field 'aService'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'AService': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:609)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:116)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:367)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1682)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:666)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:526)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:344)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:342)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:159)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1321)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1232)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:606)
... 13 more
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'AService': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:427)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:293)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:342)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:159)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1321)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1232)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:606)
... 26 more
这时候Spring就不能解决循环依赖了,看一下调的这个方法,修改的是哪个属性:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
// 是否自动尝试解析 Bean 之间的循环引用
private boolean allowCircularReferences = true;
public void setAllowCircularReferences(boolean allowCircularReferences) {
this.allowCircularReferences = allowCircularReferences;
}
}
先来看看Spring传说中的三级缓存
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
/**
* 单例对象缓存,一级缓存
**/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/**
* 单例工厂的缓存,二级缓存
**/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/**
* 早期的单例对象【未进行初始化的对象】缓存,三级缓存
**/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/**
* 已注册包含 BeanName 的单例集合,按注册顺序排序
**/
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
/**
* 当前正在创建的单例 BeanName 集合
**/
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
/**
* 当前创建检查中排除的 BeanName 集合
**/
private final Set<String> inCreationCheckExclusions =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
}
二三级缓存的叫法可能会不一样,这没关系,每个人都有自己的理解,但是一级缓存一定是单例对象缓存。
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
/**
* 至少已经创建一次的 BeanName 集合
**/
private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
}
源码解析
那我们就从源码层面看看Spring是怎么解决循环依赖的,代码从AbstractBeanFactory的doGetBean()
方法开始:
protected <T> T doGetBean(final String name,
@Nullable final Class<T> requiredType,
@Nullable final Object[] args,
boolean typeCheckOnly) throws BeansException {
/**
* 获取规范的 BeanName
*
* 这里不使用 name 直接作为 BeanName 有两个原因:
* 1.name 可能会以 & 字符开头,表明调用者想获取 FactoryBean 对象本身的实例,
* 而非 FactoryBean 实现类所创建的 Bean 对象实例。
* 在 BeanFactory 中,FactoryBean 的实现类和其他的 Bean 存储方式是一致的,
* 即<BeanName, BeanInstance>,BeanName中是没有 & 这个字符的,
* 所以需要将 name 的首字符 & 移除,这样才能从缓存里取到 FactoryBean 创建的实例
* 2.该 Bean 对象可能存在别名
*/
final String beanName = transformedBeanName(name);
Object bean;
/**
* 第一次调用 getSingleton() 方法,检查单个缓存以手动注册单例
*
* 获取给定名称注册的(原始)单例对象
**/
Object sharedInstance = getSingleton(beanName);
// 已经创建过该实例对象
if (sharedInstance != null && args == null) {
// 获取给定 Bean 实例的对象,如果是 FactoryBean,则为 Bean 实例本身或其创建的对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 没有创建过该实例对象
else {
......
if (!typeCheckOnly) {
// 将 Bean 标记为已创建
markBeanAsCreated(beanName);
}
try {
......
// 单例则进行创建
if (mbd.isSingleton()) {
// 第二次调用 getSingleton() 方法,解决循环依赖问题
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
// 获取给定 Bean 实例的对象,如果是 FactoryBean,则为 Bean 实例本身或其创建的对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 原型则创建新的实例
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
// 获取给定 Bean 实例的对象,如果是 FactoryBean,则为 Bean 实例本身或其创建的对象
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
......
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
......
return (T) bean;
}
第一次调用DefaultSingletonBeanRegistry的getSingleton()
方法:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 先从单例缓存池【一级缓存】中获取
Object singletonObject = this.singletonObjects.get(beanName);
/**
* 单例缓存池中不存在 且 当前正在被创建
*
* 当存在循环依赖时
* 解析 A 类时,将 A 类标记为当前正在创建
* 填充 A 类的属性值时去获取并创建 B 类,此时将 B 类标记为当前正在创建
* 填充 B 类的属性值时去获取并创建 A 类,此时 A 类获取不到,但是被标记为正在创建
* 此时这个判断成立
**/
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;
}
可以看到这里就使用到了allowEarlyReference
这个属性值,如果单例缓存池中没有获取到并且允许循环依赖,那么Spring会从二级缓存中获取生产单例对象的对象工厂,获取到了就执行对象工厂方法,获取这个对象并存到三级缓存中,最后从二级缓存中移除。
当然第一次调用这个方法的时候,因为对象还没有被标记为当前正在创建,所以一级缓存中获取不到就直接返回空了。
因为不需要检查类型,所以会将其标记为至少创建一次,即加入到alreadyCreated
集合中,然后开始走创建流程。
第二次调用DefaultSingletonBeanRegistry的getSingleton()
方法:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
// 从单例缓存池中获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 当前正在销毁中,不允许创建,抛异常
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException();
}
// 如果不在 inCreationCheckExclusions 集合中,则添加到 singletonsCurrentlyInCreation 集合中
beforeSingletonCreation(beanName);
// 新单例对象
boolean newSingleton = false;
......
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
......
finally {
// 如果不在 inCreationCheckExclusions 集合中,则从 singletonsCurrentlyInCreation 集合中移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 创建完后存入一级缓存,并从二三级缓存中移除
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
第二次调用,也是先从单例缓存池中获取,如果没有获取到,则做单例对象创建前的工作,具体就是当前对象不在inCreationCheckExclusions
创建检查排除集合中,则添加到singletonsCurrentlyInCreation
当前正在创建的单例对象集合中。
然后调用singletonFactory.getObject()
方法,其实就是外面传进来的Lambda表达式,获取到单例对象。
再做单例对象创建后的工作,具体就是当前对象不在inCreationCheckExclusions
创建检查排除集合中,则从singletonsCurrentlyInCreation
当前正在创建的单例对象集合中移除。
最后将创建后的单例对象存到一级缓存中,从二三级缓存中移除。
来看一下对象工厂是怎么生产这个单例对象的,AbstractAutowireCapableBeanFactory的createBean()
方法如下:
protected Object createBean(String beanName,
RootBeanDefinition mbd,
@Nullable Object[] args) throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
......
try {
/**
* 给 BeanPostProcessors 一个返回代理而不是目标 Bean 实例的机会【重要】
* 但此时还没有创建代理对象,此时没有对象,只有 BeanDefinition
*
* 第一次调用后置处理器【跟 AOP 有关】
* 此时对象还没有实例化,只有 BeanDefinition
* 无法进行代理,只是将切面找出来进行缓存
*/
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException();
}
try {
/**
* 实例化 Bean
**/
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException();
}
}
一堆代码,真正做事的还是doCreateBean()
方法:
protected Object doCreateBean(final String beanName,
final RootBeanDefinition mbd,
final @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
/**
* 第二次调用后置处理器【推断构造方法来实例化 Bean,推断不出来则使用默认无参构造器】
*/
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
/**
* 此时还未完成依赖 Bean 的注入,仅仅只是实例化
**/
// 获取包装实例
final Object bean = instanceWrapper.getWrappedInstance();
// 获取包装的类
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
......
/**
* 急于缓存单例,以便即使在诸如 BeanFactoryAware 之类的生命周期接口触发时也能够解析循环引用
* 需要暴露早期单例对象
* 是单例 且 允许循环依赖 且 当前正在创建
**/
boolean earlySingletonExposure = (mbd.isSingleton()
// 默认为 True,除非修改了这个属性
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
/**
* 第四次调用后置处理器【Spring 借助了这一次后置处理器的调用外加两次重载的 getSingleton() 方法来解决循环依赖】
*
* SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
* exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
*
* 存入二级缓存,并添加到已经注册的单例集合中
*/
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 初始化 Bean 实例
Object exposedObject = bean;
try {
/**
* 通过调用两个后置处理器的方法,完成 Bean 属性的填充【或者说自动注入】【非常重要】
*
* 第五次调用后置处理器【返回 True 才会进行属性填充,可以干预某个 Bean 的装配填充】
*
* 如果是循环依赖,可能 AOP 代理是在这一步完成的
*
* InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
* ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName);
*
* 第六次调用后置处理器【完成属性填充】
*
* InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
* PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
* pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
*/
populateBean(beanName, mbd, instanceWrapper);
/**
* 通过调用两次后置处理器,完成 Bean 的初始化【AOP】
*
* 第七次调用后置处理器【BeanPostProcessor 的直接实现类调用】
*
* Object current = processor.postProcessBeforeInitialization(result, beanName);
*
* 第八次调用后置处理器【BeanPostProcessor 的直接实现类调用】
*
* Object current = processor.postProcessAfterInitialization(result, beanName);
*/
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
......
}
......
return exposedObject;
}
第二次调用后置处理器推断构造方法进行实例化代码比较长也比较复杂,有空专门写一篇博客来解析一下里面的逻辑,这里只要知道通过这一步能把对象实例化出来。
然后Spring会判断是否把当前实例化的早期对象暴露出去,用的也是allowCircularReferences
这个属性。
因为第二次调用getSingleton()
方法时,前期的准备工作已经将当前对象标记为当前正在创建,所以只要是单例对象且allowCircularReferences
这个属性值不改,这里就会进行一个暴露的操作。
暴露操作就在addSingletonFactory()
方法中:
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
// 一级缓存缓存中不存在
if (!this.singletonObjects.containsKey(beanName)) {
// 将早期对象【还未进行初始化的对象】存入二级缓存,用于解决循环依赖
this.singletonFactories.put(beanName, singletonFactory);
// 从三级缓存中移除
this.earlySingletonObjects.remove(beanName);
// 添加到已注册集合中
this.registeredSingletons.add(beanName);
}
}
}
主要逻辑就是加入到二级缓存中
这里第四次调用的后置处理器,其实也可以理解为一个缓存,将当前早期对象,存到这个后置处理器中,因为这里传进去的参数,会原封不动的返回回来,看一下代码:
protected Object getEarlyBeanReference(String beanName,
RootBeanDefinition mbd,
Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 遍历所有的 BeanPostProcessor
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp =
(SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
它把bean
对象赋给了exposedObject
变量,然后调用getEarlyBeanReference()
方法,而这个方法内部什么也没干,除非子类重写了这个方法,否则就是将exposedObject
原封不动的返回出去了。
早期对象已经实例化出来了,也进行了暴露,然后开始执行populateBean
方法进行属性填充操作。
AutowiredAnnotationBeanPostProcessor组件用来处理@Autowired
注解,CommonAnnotationBeanPostProcessor组件用来处理@Resource
注解。
第六次调用后置处理器这里主要是调用AutowiredAnnotationBeanPostProcessor的inject()
方法进行属性填充的:
protected void inject(Object bean,
@Nullable String beanName,
@Nullable PropertyValues pvs) throws Throwable {
// 需要注入的属性元素
Field field = (Field) this.member;
Object value;
// 已缓存
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
// 依赖描述符
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
// 设置依赖描述符包含的类【不是被包含的类】
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
// 类型转换器【SimpleTypeConverter】
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
// 解决依赖【重要】
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
// 将指定的 Bean 注册为依赖于自动装配的 Bean
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName)
&& beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
// 封装为 ShortcutDependencyDescriptor 快捷依赖描述符
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc,
autowiredBeanName,
field.getType()
);
}
}
}
else {
this.cachedFieldValue = null;
}
// 标记为已缓存
this.cached = true;
}
}
}
......
}
}
最重要的就是resolveDependency()
方法解决依赖,最后调用的是doGetBean()
方法去获取依赖的对象,流程和上面说的一样。
所以当填充AService
的属性值时,会调用doGetBean()
方法去创建BService
,然后填充BService
的属性值时,又会调用doGetBean()
方法去创建AService
,但是因为AService
的早期对象已经存在于二级缓存中了,所以第一个getSingleton()
方法会调用后置处理器的getEarlyBeanReference()
方法,将之前缓存的早期对象拿出来,填充到BService
属性值中,然后对BService
进行初始化,完成之后再将其填充给AService
,在对AService
进行初始化,最后两个类都被填充完毕、初始化完成,成为被Spring容器管理的Bean。
总结一下,Spring借助了三级缓存【通过调用重载的getSingleton()
方法】和一次后置处理器的调用来解决循环依赖。
为什么原型的Bean之间不能相互依赖?
因为原型的Bean不会放入到三级缓存中,Spring不知道该先创建哪个,所以Spring源码里就直接报错了,但是相互引用的两个Bean不全都是原型的,Spring可以解决。
为什么用构造方法注入的Bean不能相互依赖?
因为推断构造方法进行实例化在暴露早期对象之前,Spring已经无法通过推断构造方法将对象进行实例化了,更别说暴露了,所以也就获取不到早期对象。