Spring Bean 完整生命周期

Spring Bean 完整生命周期

Bean 生命周期分四大阶段:实例化 → 填充属性(依赖注入) → 初始化 → 销毁配合扩展接口、注解、后置处理器完整流程,同时区分单例 Bean多例 Bean差异。

前置说明

  1. 执行入口:refresh()finishBeanFactoryInitialization()实例化所有非懒加载单例
  2. 核心扩展点:BeanPostProcessor(贯穿初始化前后,最重要后置处理器)
  3. 多例 Bean:容器不管理销毁,仅执行到初始化阶段,容器关闭不会执行销毁方法

一、完整生命周期分步流程(单例 Bean)

阶段 1:Bean 实例化 Instantiate

Spring 根据 BeanDefinition 信息创建对象,两种方式:

  1. 无参构造反射newInstance()
  2. 工厂方法factory-method

此时对象仅仅 new 出来,所有属性都是默认 null,依赖还未注入。

阶段 2:提前暴露工厂(解决循环依赖关键)

实例化完成后,立即将当前 Bean 的ObjectFactory存入三级缓存 singletonFactories。 作用:如果产生循环依赖,其他 Bean 可以提前拿到半成品对象(支持 AOP 代理)。

阶段 3:属性填充 PopulateBean(依赖注入)

给实例化后的对象填充属性、完成依赖注入,三种注入方式:

  1. @Autowired/@Resource字段注入
  2. set 方法注入
  3. 构造器注入(实例化阶段就完成,不走这里)

流程细节:

  1. 解析所有需要注入的依赖;
  2. 递归获取依赖 Bean(触发依赖 Bean 完整生命周期);
  3. 通过反射给当前 Bean 赋值;

循环依赖就是在这一步触发,依靠三级缓存拿到半成品完成注入。

阶段 4:执行 BeanPostProcessor 前置处理 postProcessBeforeInitialization

BeanPostProcessor 是全局后置处理器,对所有 Bean 生效

java

运行

Object postProcessBeforeInitialization(Object bean, String beanName)

执行时机:属性填充完成,初始化方法执行之前典型场景:

  • @Value注解属性解析赋值;
  • AOP 代理创建(大部分代理在这里生成,循环依赖才会提前在三级缓存创建);

阶段 5:执行自定义初始化方法 Initialization

三层初始化逻辑,顺序固定

1. 执行Aware系列接口(按固定顺序)

Aware 作用:让 Bean 获取 Spring 容器底层资源 执行顺序:

  1. BeanNameAware:setBeanName (String name),获取当前 beanName
  2. BeanFactoryAware:setBeanFactory (BeanFactory factory),获取 Bean 工厂
  3. ApplicationContextAware:setApplicationContext (ApplicationContext ctx),获取上下文

2. 执行@PostConstruct注解方法(JSR-250 标准)

Java 官方注解,写在自定义初始化方法上,优先级高于 xml 的 init-method。

java

运行

@PostConstruct public void init(){}

3. 执行 InitializingBean 接口 afterPropertiesSet ()

Spring 内置接口,重写方法做初始化逻辑

java

运行

public void afterPropertiesSet() throws Exception;

4. 执行 xml / 注解指定的自定义 init-method

xml 配置:<bean init-method="init"/>注解:@Bean(initMethod = "init")

阶段 6:执行 BeanPostProcessor 后置处理 postProcessAfterInitialization

java

运行

Object postProcessAfterInitialization(Object bean, String beanName)

执行时机:所有初始化逻辑全部执行完毕后核心用途:

  1. AOP 正常 Bean 的动态代理生成(无循环依赖时在这里创建代理对象);
  2. 对 Bean 做包装、替换、自定义增强;

走完这一步,Bean 完全创建完成,存入一级缓存 singletonObjects,业务代码可以直接使用。

阶段 7:Bean 就绪,容器使用阶段

单例 Bean 常驻容器,每次获取直接从一级缓存返回; 多例 Bean 每次 getBean 都会完整走一遍实例化、属性填充、初始化流程。

阶段 8:容器关闭,销毁 Bean Destruction(仅单例 Bean 执行)

调用ctx.close()/registerShutdownHook()触发销毁流程,三层销毁逻辑,顺序固定:

1.@PreDestroy注解方法(JSR 标准,优先级最高)

java

运行

@PreDestroy public void destroy(){}

2. DisposableBean 接口 destroy () 方法

Spring 内置销毁接口

java

运行

public void destroy() throws Exception;

3. xml/@Bean 指定的 destroy-method

xml:<bean destroy-method="close"/>注解:@Bean(destroyMethod = "close")

多例 Bean:Spring 容器不缓存、不管理销毁,关闭容器不会执行任何销毁方法。

二、生命周期执行顺序极简总结(背诵版)

  1. 实例化对象(new)
  2. 存入三级缓存(解决循环依赖)
  3. 填充属性、依赖注入
  4. BeanPostProcessor before 初始化
  5. Aware 接口回调 → @PostConstruct → InitializingBean → init-method
  6. BeanPostProcessor after 初始化(AOP 代理生成)
  7. Bean 放入一级缓存,业务使用
  8. 容器关闭:@PreDestroy → DisposableBean → destroy-method

三、高频面试延伸问题

1. BeanPostProcessor 和 InitializingBean 的区别

  1. BeanPostProcessor全局处理器,所有 Bean 都会经过,分前后两个方法;AOP 核心依赖它;
  2. InitializingBean单个 Bean 自身初始化接口,仅当前 Bean 执行,只有 afterPropertiesSet 一个方法。

2. @PostConstruct 和 InitializingBean、init-method 优先级

优先级从高到低:@PostConstruct>InitializingBean#afterPropertiesSet()> xml/@Bean init-method

3. 为什么多例 Bean 不会执行销毁方法?

多例 Bean 不会存入一级缓存,容器不持有多例 Bean 的引用,无法追踪对象,GC 由 JVM 管理,容器关闭无法主动调用销毁逻辑。

4. AOP 代理对象在生命周期哪个阶段创建?

两种情况:

  1. 无循环依赖:在postProcessAfterInitialization(初始化之后)创建代理;
  2. 存在循环依赖:提前从三级缓存 ObjectFactory 生成代理,存入二级缓存。

四、完整流程图文字版

plaintext

加载BeanDefinition ↓ 实例化Bean(反射new对象) ↓ 存入三级缓存 singletonFactories ↓ populateBean 属性填充、依赖注入 ↓ BeanPostProcessor.postProcessBeforeInitialization ↓ 执行Aware接口(BeanName→BeanFactory→ApplicationContext) ↓ 执行@PostConstruct方法 ↓ 执行InitializingBean.afterPropertiesSet() ↓ 执行自定义init-method ↓ BeanPostProcessor.postProcessAfterInitialization(创建AOP代理) ↓ 存入一级缓存 singletonObjects ,应用使用Bean ↓ 容器关闭 ↓ 执行@PreDestroy ↓ 执行DisposableBean.destroy() ↓ 执行自定义destroy-method