Spring核心问题回顾1:ioc容器创建的大致过程、bean的生命周期、解决循环依赖为什么需要三级缓存

1、spring容器中的bean是如何获取的?

spring 容器中的bean可以通过xml文件或者注解,通过解析放到spring容器中的对象中:
在这里插入图片描述

2、spring容器的大致创建过程?

Spring容器创建的大致过程有如下5个步骤
1)通过BeanDefinitionReader解析bean的定义信息
2)通过beanFactoryPostProcessor,将bean定义信息中的占位符的信息进行填充,得到完整的beanDefinition对象
3)bean生命周期之一:创建bean对象
4)bean生命周期之二:使用bean对象
5)bean生命周期之三:销毁bean对象
在这里插入图片描述

3、什么是beanFactory?

首先beanFactory基本可以理解为spring容器,但是它是一个根接口。我们用的ApplicationContext就是它的子接口

beanFacroty定义了在这个容器中的bean所具有的所有规范,比如实现的方法等等。
在这里插入图片描述

在这里插入图片描述

4、postProcessor该怎么理解?

在容器创建过程中,spring中会有非常多的postProcessor,有些地方翻译为后置处理器,很容易把人弄晕

其实把它叫做增强处理器会更合适一点。比如在2、spring容器的大致创建过程图中,当加载了beanDefinition后,有些bean的占位符的属性是没有赋值的,这些初始值在配置文件中(properties)配置好了,这个时候需要进行替换。那么此时就可以调用beanFactoryPostProcessor进行处理。

针对beanFactory中对象的增强可以使用beanFactoryPostProcessor,针对自定义bean的增强可以使用beanPostProcessor。
在这里插入图片描述

在这里插入图片描述

5、bean的生命周期?

bean的生命周期,大致可以分为以下5步,当然最核心的就是前3步。
1)bean的实例化
2)bean的属性赋值
3)bean的初始化
4)bean的使用
5)bean的销毁

这里特别要注意的是AOP是在bean对象的执行postProcessorAfterInitialization时得到的,而产生AOP的前提,是要在配置类上加@EnableAspectJAutoProxy注解,该注解最终会为spring容器注册一个id为internalAutoProxyCreator,类型为AnnotationAwareAspectJAutoProxyCreator的组件,正是因为注册了该组件,所以才会去调用wrapIfNecessary方法。这样就把AOP的大致原理给基本介绍了下。这一块的详细分析见:
Spring注解驱动开发学习总结12:AOP原理 - @EnableAspectJAutoProxy注解作用分析
在这里插入图片描述

6、BeanFactory和FactoryBean的区别?

相同点
首先BeanFactory和FactoryBean都是接口,都是用来创建bean的,这个首先一定要明确和清楚。

不同点
通过第2,3,5小节的介绍,可以很清楚地明白了beanFactory相当于我们的spring 容器,它是根接口,定义了spring容器的基本规范,定义了一个bean的完整生命周期。

那如果我们自定义的一个bean不希望经历这么复杂的生命周期,同时又希望spring容器能把这个bean能加入到容器中,这个时候就可以把这个bean实现FactoryBean接口。只需要实现它的3个方法,就可以成功注入进spring容器中。这样的bean就叫做factoryBean。

在这里插入图片描述

7、spring解决循环依赖,为什么需要三级缓存?使用二级缓存可以解决么?

首先明确循环依赖产生的原因,是2个或2个以上的对象存在相互依赖的情况,当bean在进行属性赋值的时候,就会去找它所需要的bean,当相互依赖时,就存在循环依赖问题。

解决循环依赖问题的核心其实就1个点:
实例化和初始化过程分离。在属性赋值前,已经进行了实例化了;

综上,其实使用2个缓存就可以解决循环依赖问题了

那Spring为什么还需要三级缓存呢?可以先看一下Spring的三级缓存对象:
1)一级缓存:singletonObjects:Map<String, Object>
2)二级缓存:earlySingletonObjects:Map<String, Object>
3)三级缓存:singletonFactories:Map<String, ObjectFactory<?>>

可以看到三级缓存singletonFactories中保存的是ObjectFactory,为啥三级缓存保存的对象是ObjectFactory呢?首先要理解下ObjectFactory是什么。

ObjectFactory是一个函数式接口。可以将lambda表达式作为参数放到方法的实参中,在方法执行的时候,并不会实际调用当前lambda表达式。只有在调用getObject方法的时候,才会去调用lambda表达式。

在第5小结中,在postProcessorAfterInitialization中,如果该bean是进行了AOP增强的话,那么此时就会产生一个代理对象,它会通过new来创建一个新的代理对象。这样存在一个问题,就是不知道容器什么时候会获取该bean。因此为了当容器真正需要该bean的时候,此时才会生成一个代理对象,spring容器会将该代理对象放入到二级缓存中。因此三级缓存保存的对象是ObjectFactory

在换一种解释方式,看看能不能帮助理解:对象在什么时候被暴露出去,或者被其他对象引用是没办法提前确定好的,所以只有在被调用的那一刻,才可以判断是原始对象还是代理对象。使用lambda表达式类似于一种回调机制,不暴露的时候,不需要调用执行。当需要被调用的时候,才真正地执行lambda表达式,来判断返回的到底是原始对象还是代理对象。

因此,三级缓存主要是针对AOP功能的代理对象而设计的。
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/xueping_wu/article/details/126437729