更新时间:2022-08-15 来源:黑马程序员 浏览量:
bean 的生命周期从调用 beanFactory 的 getBean 开始,到这个 bean 被销毁,可以总结为以下七个阶段:
处理名称,检查缓存→处理父子容器→处理 dependsOn→选择 scope 策略→创建 bean→类型转换处理→销毁 bean
划分的阶段和名称并不重要,重要的是理解整个过程中做了哪些事情。
1. 处理名称,检查缓存
这一步会处理别名,将别名解析为实际名称。对 FactoryBean 也会特殊处理,如果以 & 开头表示要获取 FactoryBean 本身,否则表示要获取其产品。
里针对单例对象会检查一级、二级、三级缓存。
singletonFactories 三级缓存,存放单例工厂对象。
earlySingletonObjects 二级缓存,存放单例工厂的产品对象。
如果发生循环依赖,产品是代理;无循环依赖,产品是原始对象。
singletonObjects 一级缓存,存放单例成品对象。
2. 处理父子容器
如果当前容器根据名字找不到这个 bean,此时若父容器存在,则执行父容器的 getBean 流程。父子容器的 bean 名称可以重复。
3. 处理 dependsOn
如果当前 bean 有通过 dependsOn 指定了非显式依赖的 bean,这一步会提前创建这些 dependsOn 的
bean,所谓非显式依赖,就是指两个 bean 之间不存在直接依赖关系,但需要控制它们的创建先后顺序。
4. 选择 scope 策略
对于 singleton scope,首先到单例池去获取 bean,如果有则直接返回,没有再进入创建流程。
对于 prototype scope,每次都会进入创建流程。
对于自定义 scope,例如 request,首先到 request 域获取 bean,如果有则直接返回,没有再进入创建流程。
5.1 创建 bean - 创建 bean 实例
| 有自定义 TargetSource 的情况 | 由 AnnotationAwareAspectJAutoProxyCreator 创建代理返回 | | Supplier 方式创建 bean 实例 | 为 Spring 5.0 新增功能,方便编程方式创建 bean 实例 | | FactoryMethod 方式 创建 bean 实例 | ① 分成静态工厂与实例工厂;② 工厂方法若有参数,需要对工厂方法参数进行解析,利用 resolveDependency;③ 如果有多个工厂方法候选者,还要进一步按权重筛选 | | AutowiredAnnotationBeanPostProcessor | ① 优先选择带 @Autowired 注解的构造;② 若有唯一的带参构造,也会入选 | | mbd.getPreferredConstructors | 选择所有公共构造,这些构造之间按权重筛选 | | 采用默认构造 | 如果上面的后处理器和 BeanDefiniation 都没找到构造,采用默认构造,即使是私有的 |5.2 创建 bean - 依赖注入
| ------------------------------------ | ------------------------------------------------------------ | | 有自定义 TargetSource 的情况 | 由 AnnotationAwareAspectJAutoProxyCreator 创建代理返回 | | Supplier 方式创建 bean 实例 | 为 Spring 5.0 新增功能,方便编程方式创建 bean 实例 | | FactoryMethod 方式 创建 bean 实例 | ① 分成静态工厂与实例工厂;② 工厂方法若有参数,需要对工厂方法参数进行解析,利用 resolveDependency;③ 如果有多个工厂方法候选者,还要进一步按权重筛选 | | AutowiredAnnotationBeanPostProcessor | ① 优先选择带 @Autowired 注解的构造;② 若有唯一的带参构造,也会入选 | | mbd.getPreferredConstructors | 选择所有公共构造,这些构造之间按权重筛选 | | 采用默认构造 | 如果上面的后处理器和 BeanDefiniation 都没找到构造,采用默认构造,即使是私有的 |5.3 创建 bean - 初始化
| **要点** | **总结** | | --------------------- | ------------------------------------------------------------ | | 内置 Aware 接口的装配 | 包括 BeanNameAware,BeanFactoryAware 等 | | 扩展 Aware 接口的装配 | 由 ApplicationContextAwareProcessor 解析,执行时机在 postProcessBeforeInitialization | | @PostConstruct | 由 CommonAnnotationBeanPostProcessor 解析,执行时机在 postProcessBeforeInitialization | | InitializingBean | 通过接口回调执行初始化 | | initMethod | 根据 BeanDefinition 得到的初始化方法执行初始化,即 `<bean init-method>` 或 @Bean(initMethod) | | 创建 aop 代理 | 由 AnnotationAwareAspectJAutoProxyCreator 创建,执行时机在 postProcessAfterInitialization |
5.4 创建 bean - 注册可销毁 bean
在这一步判断并登记可销毁 bean
判断依据
如果实现了 DisposableBean 或 AutoCloseable 接口,则为可销毁 bean
如果自定义了 destroyMethod,则为可销毁 bean
如果采用 @Bean 没有指定 destroyMethod,则采用自动推断方式获取销毁方法名(close,shutdown)
如果有 @PreDestroy 标注的方法
存储位置
singleton scope 的可销毁 bean 会存储于 beanFactory 的成员当中
自定义 scope 的可销毁 bean 会存储于对应的域对象当中
prototype scope 不会存储,需要自己找到此对象销毁
存储时都会封装为 DisposableBeanAdapter 类型对销毁方法的调用进行适配。