Spring 的 Bean 的生命周期

发布时间 2023-09-28 03:18:27作者: 是小陈呀

Spring 框架在创建 bean 的时候都会调用 AbstractBeanFactory 类中的 doGetBean 方法;bean 的生命周期从调用 beanFactory 的 getBean 开始,到这个 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. 创建 bean(关键阶段)

5.1 创建 bean 实例

要点 总结
AutowiredAnnotationBeanPostProcessor 1. 优先选择带 @Autowired 注解的构造;2. 若有唯一的带参构造,也会入选。
采用默认构造 如果上面的后处理器和 BeanDefiniation 都没找到构造,采用默认构造,即使是私有的。

5.2 依赖注入

要点 总结
AutowiredAnnotationBeanPostProcessor 识别 @Autowired@Value 标注的成员,封装为 InjectionMetadata 进行依赖注入。
CommonAnnotationBeanPostProcessor 识别 @Resource 标注的成员,封装为 InjectionMetadata 进行依赖注入
AUTOWIRE_BY_NAME 根据成员名字找 bean 对象,修改 mbd 的 propertyValues,不会考虑简单类型的成员。
AUTOWIRE_BY_TYPE 根据成员类型执行 resolveDependency 找到依赖注入的值,修改 mbd 的 propertyValues
applyPropertyValues 根据 mbd 的 propertyValues 进行依赖注入(即 xml 中 <property name ref | value />)

5.3 初始化

要点 总结
内置 Aware 接口的装配 包括BeanNameAwareBeanFactoryAware 等。
扩展 Aware 接口的装配 ApplicationContextAwareProcessor 解析,执行时机在 postProcessBeforeInitialization
PostConstruct CommonAnnotationBeanPostProcessor 解析,执行时机在 postProcessBeforeInitialization
InitializingBean 通过接口回调执行初始化。
initMethod 根据 BeanDefinition 得到的初始化方法执行初始化,即 <bean init-method> 或 @Bean(initMethod)

5.4 注册可销毁的 bean
在这一步判断并登记可销毁 bean。

  • 判断依据

    • 如果实现了 DisposableBeanAutoCloseable 接口,则为可销毁 bean。
    • 如果自定义了 destroyMethod,则为可销毁 bean。
    • 如果采用 @Bean 没有指定 destoryMethod,则采用自动推断方式获取销毁方法名(close,shutdown)。
    • 如果由 @PreDestroy 标注的方法。
  • 存储位置

    • singleton scope 的可销毁 bean 会存储于 beanFactory 的成员当中。
    • 自定义 scope 的可销毁 bean 会存储于对于的域对象当中。
    • prototype scope 不会存储,需要自己找到此对象销毁。
  • 存储时都会封装为 DisposableBeanAdapter 类型对销毁方法的调用进行适配。

6. 类型转换处理

  • 如果 getBeanrequiredType 参数与实际得到的对象类型不同,会尝试进行类型转换。

7. 销毁 bean

  • 销毁时机
    • singleton bean 的销毁在 ApplicationContext.close 时,此时会找到所有 DisposableBean 的名字,逐一销毁。
    • 自定义 scope bean 的销毁在作用域对象生命周期结束时。
    • prototype bean 的销毁可以通过自己手动调用,AutowireCapableBeanFactory.destroyBean 方法执行销毁。
  • 同一 bean 中不同形式销毁方法的调用次序
    • 优先后处理器销毁,即 @PreDestroy
    • 其次 DisposableBean 接口销毁。
    • 最后 destroyMethod 销毁(包括自定义名称,推断名称,AutoCloseable 接口多选一)。