Spring容器初始化流程以及三级缓存原理
Sring容器启动流程
- 容器准备阶段
- 获取一个默认的
DefaultListableBeanFactory
的BeanFactory. - 扫描注册一些内置的
BeanPostProcessor
,这些后置处理器是对容器的功能提供支持,比如
ApplicationContextAwareProcessor
,是为了确保其余处理器在执行的时候如果要获取上下文确保能获取到。 - 扫描注册
BeanFactoryPostProcessor
,扫描容器的后置处理器并且注册。BeanDefinitionRegistryPostProcessor就是一个容器后置处理器,能够修改Bean的定义信息 - 扫描和注册Bean的定义信息
BeanDefinition
- 获取一个默认的
- 执行容器后置处理器
BeanFactoryPostProcessor
- 执行普通的容器后置处理器
- 执行
BeanDefinitionRegistryPostProcessor
,修改bean的定义信息
-
实例化BeanBean的后置处理器发挥作用
-
实例化之前会调用`InstantiationAwareBeanPostProcessor` 类型的处理器的 `postProcessBeforeInstantiation()` 方法实现代理的时机
不过基本不会在这一步进行对象的代理,这个时候对象的属性还没赋值,可能还有自定义操作没有完成,得到的是半成品。
-
实例化Bean
-
实例化之前会调用
InstantiationAwareBeanPostProcessor
类型的处理器的postProcessAfterInstantiation()
方法;根据返回结果决定是否继续属性赋值。
-
在属性注入之前,执行
InstantiationAwareBeanPostProcessor
接口中的方法postProcessPropertyValues()
,能够对属性进行操作
-
实例化之前会调用`InstantiationAwareBeanPostProcessor` 类型的处理器的 `postProcessBeforeInstantiation()` 方法实现代理的时机
- 属性赋值
- 执行部分特殊的
BeanPostProcessor
,例如ApplicationContextAware
,会执行相应的方法。 - 初始化Bean
-
初始化之前执行所有注册的
BeanPostProcessor
的postProcessBeforeInitialization()
方法。大部分的后置处理器在这里执行,包括自定义的,内置的处理器在各个阶段都有执行。 -
初始化Bean,执行初始化方法,如
init-method
或通过@PostConstruct
注解标注的方法。 -
初始化之后执行所有注册的
BeanPostProcessor
的postProcessAfterInitialization()
方法。代理对象的创建一般是在这个时候创建的,这时候目标对象已经设置完成,可以代理
-
- 注册销毁方法
- 发布容器刷新完成事件
循环依赖以及缓存
循环依赖
原因
例如,类 A 依赖类 B,同时类 B 又依赖类 A。在对象创建和依赖注入的过程中,如果不加以处理,就会陷入死循环。
解决办法
spring引入了多级缓存机制,在实例化结束后就把对象放入到二级缓存,可以拿到这个不完全的对象来使用。
存在问题
二级缓存中存放的是真正的目标对象,因为代理对象要在初始化之后才会创建,所以这时候只有目标对象,这个时候如果被代理的对象被注入的话,拿到的就是目标对象,代理功能就无法使用了。
代理对象解决办法
使用三级缓存,在实例化对象之后会把一个对象工厂放入到三级缓存。