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 三级缓存中拿出,放入二级缓存
// 从三级缓存中拿出,放入二级缓存,并删除三级缓存
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
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 != NULL_OBJECT ? singletonObject : null);
}
3 第三级缓存中为什么要添加ObjectFactory对象,直接保存实例对象不行吗
不行,因为假如你想对添加到三级缓存中的实例对象进行增强,直接用实例对象是行不通的。
针对这种场景spring是怎么做的呢?
答案就在AbstractAutowireCapableBeanFactory类doCreateBean方法的这段代码中
它定义了一个匿名内部类,通过getEarlyBeanReference方法获取代理对象,其实底层是通过AbstractAutoProxyCreator类的getEarlyBeanReference生成代理对象
Spring 的做法就是在 ObjectFactory 中去提前创建代理对象。它会执行 getObject() 方法来获取到 Bean。实际上,它真正执行的方法如下:
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
// 如果需要代理,这里会返回代理对象;否则返回原始对象
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
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
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