EverBody,直蹦主题,了解过Spring生命周期吗?
大致流程(粗略的概括理解,当然详细的还需要更加深入的读源码):
IOC思想在图中有所展示,什么是IOC?
控制反转,大家都能答出来,什么是控制反转呢?
例如,你现在30好几了,还没对象,怎么办呢,诶这个时候,有个人说有个XX婚介所,你可以在里面去找对象,里面有很多对象,这里的婚介所相当于IOC容器,然后容器里的对象,又不是平白无故出来的,是你说需要对象,并且有可能你需要漂亮的,好,那么你可以通过XML或者注解的方式,也就是图中的XmlBeanDefinitionReader读取你的需求提交的BeanDefinition定义信息中,好接下来是不是需要示例话对象了,正常思想是不是new或者反射等实例化对象,这个时候我们不需要new,我们直接交给BeanFactory工厂,交给它来通过反射找到构造器来创建你需要的对象,光创建好还不行呀,因为你的需求里,说了要年轻,貌美的,这是什么,这是属性,接下来需要填充属性了,BeanPostProcessor.before(前置增强)是什么呢,是你如果对生成的对象还不满意,你还可以进行扩展,同理BeanPostProcessor.after(后置增强)也是此意,这里用到的是AOP思想,最后,都做好后初始化生成一个完整对象。这是我最简单粗暴的理解方式。
说一说,spring是如何解决循环依赖问题的?
我们都知道,在spring中属性的赋值是通过自动注入完成的,那么在自动注入的过程中它又是如何解决循环依赖的呢?
首先我们要明白什么是循环依赖。(三级缓存解决的是构造器的循环依赖,不是setter循环依赖)
就是假如对象A里面有一个属性是对象B,而对象B里有一个属性是对象A,这会造成什么呢?
陷入一个死循环,一直相互依赖,就会报错。这时候spring就想到了,它是怎么解决的呢?
上源码:
// 一级缓存,存放的是已经实例化,并且初始化后的单例对象(也叫单例池)
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 三级缓存,存放的是 ObjectFactory,通过 ObjectFactory 的 getObject()可以拿到已经实例化,但是并未初始化的对象
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
// 二级缓存,存放的是已经实例化,但是并未初始化的对象
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
spring 源码中解决循环依赖的核心类是:DefaultSingletonBeanRegistry ,核心的代码如下:
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 对象
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 通过调用 ObjectFactory 的 getObject() 获取(并不完整的)对象
singletonObject = singletonFactory.getObject();
// 把获取到的对象保存的二级缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
// 从三级缓存中移除对象
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
接下来,我们再回到,对象A和对象B的问题。
通过上面源码,我们来解析当对象A在实例化时,容器通过构造器,将对象A保存到三级缓存也就是singletonFactories中,好接下来,依赖注入,好这时候发现对象B也需要实例化,此时A还只是通过构造器刚保存到singletonFactories(第三级缓存)中,我们接下来去实例化对象B,而再准备给B对象注入属性的时候发现对象A需要实例化,这时候重点来了,它是去获取缓存中的对象A,然后对象B实例化,然后B对象的在二级缓存和三级缓存中删除,再回到对象A中,B对象实例化初始化之后,A对象也初始化成功,同样A对象再三级缓存和二级缓存中删除,这样循环依赖问题就基本上解决了,下面用步骤让大家看一下。
步骤 操作 三层列表中的内容
1 开始初始化对象A
singletonFactories:
earlySingletonObjects:
singletonObjects:
2 调用A的构造,把A放入singletonFactories
singletonFactories:A
earlySingletonObjects:
singletonObjects:
3 开始注入A的依赖,发现A依赖对象B
singletonFactories:A
earlySingletonObjects:
singletonObjects:
4 开始初始化对象B
singletonFactories:A,B
earlySingletonObjects:
singletonObjects:
5 调用B的构造,把B放入singletonFactories
singletonFactories:A,B
earlySingletonObjects:
singletonObjects:
6 开始注入B的依赖,发现B依赖对象A
singletonFactories:A,B
earlySingletonObjects:
singletonObjects:
7
开始初始化对象A,发现A在singletonFactories里有,则直接获取A,
把A放入earlySingletonObjects,把A从singletonFactories删除
singletonFactories:B
earlySingletonObjects:A
singletonObjects:
8 对象B的依赖注入完成
singletonFactories:B
earlySingletonObjects:A
singletonObjects:
9
对象B创建完成,把B放入singletonObjects,
把B从earlySingletonObjects和singletonFactories中删除
singletonFactories:
earlySingletonObjects:A
singletonObjects:B
10 对象B注入给A,继续注入A的其他依赖,直到A注入完成
singletonFactories:
earlySingletonObjects:A
singletonObjects:B
11
对象A创建完成,把A放入singletonObjects,
把A从earlySingletonObjects和singletonFactories中删除
singletonFactories:
earlySingletonObjects:
singletonObjects:A,B
12 循环依赖处理结束,A和B都初始化和注入完成
singletonFactories:
earlySingletonObjects:
singletonObjects:A,B
水平能力有限,如有不对,请大家指出。
本文详细解释了Spring框架中如何处理循环依赖问题,介绍了三级缓存机制,并通过具体步骤展示了对象A与B之间的循环依赖是如何被解决的。
3850

被折叠的 条评论
为什么被折叠?



