https://blog.csdn.net/shenchaohao12321/article/details/114485179

1 createBeanInstance:实例化,其实也就是调用对象的构造方法实例化对象

2 populateBean:填充属性,这一步主要是多bean的依赖属性进行填充

3 initializeBean:调用spring xml中的init 方法。

1 三层缓存

一级缓存 singletonObjects:单例对象的cache
二级缓存 searlySingletonObjects :提前暴光的单例对象的Cache
三级缓存 singletonFactories : 单例对象工厂的

一级缓存:singletonObject:,该缓存key = beanName, value = bean;这里的bean是已经创建完成的,该bean经历过实例化->属性填充->初始化以及各类的后置处理。因此,一旦需要获取bean时,我们第一时间就会寻找一级缓存
二级缓存:earlySingletonObjects:,该缓存key = beanName, value = bean;这里跟一级缓存的区别在于,该缓存所获取到的bean是提前曝光出来的,是还没创建完成的。也就是说获取到的bean只能确保已经进行了实例化,但是属性填充跟初始化肯定还没有做完,因此该bean还没创建完成,仅仅能作为指针提前曝光,被其他bean所引用
三级缓存:singletonFactories: 该缓存key = beanName, value = beanFactory;在bean实例化完之后,属性填充以及初始化之前,如果允许提前曝光,spring会将实例化后的bean提前曝光,也就是把该bean转换成beanFactory并加入到三级缓存。在需要引用提前曝光对象时再通singletonFactory.getObject()获取

2 三级缓存中拿出,放入二级缓存

  1. // 从三级缓存中拿出,放入二级缓存,并删除三级缓存
  2. protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  3. Object singletonObject = this.singletonObjects.get(beanName);
  4. if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
  5. synchronized (this.singletonObjects) {
  6. singletonObject = this.earlySingletonObjects.get(beanName);
  7. if (singletonObject == null && allowEarlyReference) {
  8. ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
  9. if (singletonFactory != null) {
  10. singletonObject = singletonFactory.getObject();
  11. this.earlySingletonObjects.put(beanName, singletonObject);
  12. this.singletonFactories.remove(beanName);
  13. }
  14. }
  15. }
  16. }
  17. return (singletonObject != NULL_OBJECT ? singletonObject : null);
  18. }

3 第三级缓存中为什么要添加ObjectFactory对象,直接保存实例对象不行吗

不行,因为假如你想对添加到三级缓存中的实例对象进行增强,直接用实例对象是行不通的。
针对这种场景spring是怎么做的呢?
答案就在AbstractAutowireCapableBeanFactory类doCreateBean方法的这段代码中

image.png
它定义了一个匿名内部类,通过getEarlyBeanReference方法获取代理对象,其实底层是通过AbstractAutoProxyCreator类的getEarlyBeanReference生成代理对象

Spring 的做法就是在 ObjectFactory 中去提前创建代理对象。它会执行 getObject() 方法来获取到 Bean。实际上,它真正执行的方法如下:

  1. protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
  2. Object exposedObject = bean;
  3. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  4. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  5. if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
  6. SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
  7. // 如果需要代理,这里会返回代理对象;否则返回原始对象
  8. exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
  9. }
  10. }
  11. }
  12. return exposedObject;
  13. }

4 整体流程

1 从各级缓存中获得bean
2 检测a是否在创建中
3 将a,放入创建中集合
4 实例化bean
5 将bean放入三级缓存中
6 属性注入发现b
7 getsingleton(b)
8 检测b是否在创建中
9 加入创建中集合
10 实例化b
11 将b工厂对象放入三级缓存
12 属性依赖a
13 尝试各级缓存找a,发现在三级缓存里,调用早期工厂的objeat()
14 getEarlyBeanReference
15 调用spring aop生成aop-a
16 将aop-a放入二级缓存,删除三级缓存
17 返回创建的其他属性填充
18 创建b完成,移除创建中b
19 返回a的其他属性创建
20 初始化a完成,移除创建中a

image.png

5 二级缓存可以吗

1 不能解决aop问题
2 单例不能保证

6 第二级缓存的额价值

TestService1注入到TestService3又需要从第三级缓存中获取实例,而第三级缓存里保存的并非真正的实例对象,而是ObjectFactory对象。说白了,两次从三级缓存中获取都是ObjectFactory对象,而通过它创建的实例对象每次可能都不一样的

spring引入的第二级缓存。上面图1其实TestService1对象的实例已经被添加到第二级缓存中了,而在TestService1注入到TestService3时,只用从第二级缓存中获取该对象即可。

https://blog.csdn.net/chaitoudaren/article/details/105060882
aop是在 初始化过程中,用post-pocessor