以下文字全是自己一步一步debug后手打的总结,仅供自己以后复习使用,不敢保证全对,如有错误,欢迎指出。
前置环境:为了更好地理解和debug我这里每个service里面注入了2个service
@Component
public class AService {
@Autowired
private BService bService;
@Autowired
private CService cService;
public AService(){
System.out.println("AService构造函数");
}
}
@Component
public class BService {
@Autowired
private AService aService;
@Autowired
private CService cService;
public BService(){
System.out.println("BService构造函数");
}
}
@Component
public class CService {
@Autowired
private AService aService;
@Autowired
private BService bService;
public CService(){
System.out.println("CService构造函数");
}
}
A第一次getSingleton会先去singletonObject获取bean,没有且isSingletonCurrentlyInCreation判断是否被标记为正在创建,没有被标记则返回一个null
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
会经过一系列验证比如父子容器 dependsOn等
第二次执行有拉姆达表达式的getSingleton,里面又会尝试去获取bean Object singletonObject = this.singletonObjects.get(beanName);
没有获取到则执行 beforeSingletonCreation 去添加 singletonsCurrentlyInCreation 标记为正在创建,此时singletonsCurrentlyInCreation内只有了A数据
接着执行拉姆达表达式回调方法singletonObject = singletonFactory.getObject(); -> return createBean(beanName, mbd, args); ->doCreateBean
接着实例化bean ,Object bean = instanceWrapper.getWrappedInstance();后 java bean已经产生,但内部属性还没有注入
接着因为earlySingletonExposure为true 会将这个拉姆达表达式添加进singletonFactory(三级缓存) addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
populateBean中会执行对于A中的依赖的bean B(@AutoWired)进行getBean(B).
----------------开始重复操作----------------
调用链:AutowiredAnnotationBeanPostProcessor.postProcessProperties -> metadata.inject(bean, beanName, pvs); -> element.inject(target, beanName, pvs); -> beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); -> instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); -> return beanFactory.getBean(beanName); -> B第一次getSingleton会先去singletonObject获取bean,没有且isSingletonCurrentlyInCreation判断是否被标记为正在创建,没有被标记则返回一个null。
element.inject(target, beanName, pvs);这一步是在循环体内执行的,循环的A所有的依赖
经过一系列验证比如父子容器 dependsOn等
第二次执行有拉姆达表达式的getSingleton,里面又会尝试去获取bean Object singletonObject = this.singletonObjects.get(beanName);
没有获取到则执行 beforeSingletonCreation 去添加 singletonsCurrentlyInCreation 标记为正在创建 ,此时singletonsCurrentlyInCreation内有了2条A和B数据
接着执行拉姆达表达式回调方法singletonObject = singletonFactory.getObject(); -> return createBean(beanName, mbd, args); ->doCreateBean
接着实例化bean ,Object bean = instanceWrapper.getWrappedInstance();后 java bean已经产生,但内部属性还没有注入
接着因为earlySingletonExposure为true , addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); 会将这个拉姆达表达式添加进singletonFactory(三级缓存)
1.populateBean中会循环依赖发现了有依赖的bean A(@AutoWired)进行getBean(A).
element.inject(target, beanName, pvs);这一步是在循环体内执行的,循环的B所有的依赖
此时Object sharedInstance = getSingleton(beanName);发生了变化
singletonObjects没A
isSingletonCurrentlyInCreation对A = true
earlySingletonObjects没A
allowEarlyReference = true
singletonFactories有A的工厂 此时就去调用工厂内部的ObjectFactory.getObject 生产一个A(回调当时加入工厂时的方法getEarlyBeanReference,
此处回答了为何要使用工厂三级缓存:
在此处会循环所有的后置处理器,当中会执行aop的后置处理器返回一个代理对象,如果没有三级工厂,二级中存放的只是普通的A,如:A与B都实现了切面,AB相互依赖,A实例化完成后存到二级缓存(注:当前是模拟没有三级缓存的情况),开始populateBean,发现依赖B,B开始实例化,使用二级缓存中的A,B完成流程,封装成代理对象返回,A再将代理后的B注入,之后执行aop后置处理器,返回A的代理对象,此时A代理对象中的属性B是B代理对象,但是B代理对象中的A却是普通的A。
顺便说明二级缓存的作用,分离半成品和完全体bean,除不能处理aop代理对象外,如果多线程下获取获取一个bean,可能会有线程只能获取到半成品的情况。
执行完后置处理器的返回值就已经成为了一个代理对象(Bean有接口使用的jdk动态代理,否则使用的cglib)
),但此时的A也只是一个java bean,并没有成为一个sping bean,半成品。
最后把生产出来的A放入earlySingletonObjects,再把A的工厂从singletonFactories中移除,此时只有B的工厂在三级缓存。
2.发现还有B一个依赖C,则C也去跑一遍,(populateBean之前加入了工厂三级缓存)当C跑到populateBean时,发现依赖了A则又去getBean(A),getSingleton(beanName),此时又有所不同,因为有一个半成品A已经在前面放入了earlySingletonObjects,工厂中那个已经被移除所以:
singletonObjects没A
isSingletonCurrentlyInCreation对A = true
earlySingletonObjects有A 直接return这个半成品A
C又发现依赖了B,又去getBean(B),则会触发和前面A半成品产生的操作
singletonObjects没B
isSingletonCurrentlyInCreation对B = true
earlySingletonObjects没B
allowEarlyReference = true
singletonFactories有B的工厂 此时就去调用工厂内部的ObjectFactory.getObject 生产一个B,但此时的B也只是一个java bean,并没有成为一个sping bean,半成品。
最后把生产出来的B放入earlySingletonObjects,再把B的工厂从singletonFactories中移除, 此时只有C的工厂在三级缓存。
C完成
A最后发现还有一个C,执行C的流程,C会发现依赖了A和B,则去getBean(A)和getBean(B),但是都在二级缓存earlySingletonObjects中获取到了A和B的半成品,最后A完成B、C的属性注入,至此全部完成。
最后在addSingleto()中添加到一级缓存singletonObject,清除2级缓存。