Spring Bean 生命周期
Spring Bean 的生命周期是指 Spring 容器从 Bean 的实例化到销毁的完整管理过程。其核心流程围绕 AbstractAutowireCapableBeanFactory.doCreateBean() 方法展开,主要分为以下阶段:
一、实例化(Instantiation)
Spring 容器通过反射机制调用 Bean 的构造器(默认无参构造器或指定构造器)创建原始对象实例。此时 Bean 处于“半成品”状态,所有属性均为默认值。
二、属性赋值(Populate Properties)
容器根据配置(@Autowired、@Value、@Resource 等注解或 XML 配置)执行依赖注入(DI),将依赖的 Bean 实例和配置值注入到当前 Bean 的对应字段中。此阶段由 populateBean() 方法完成。
三、Aware 接口回调(Aware Interface Callback)
若 Bean 实现了特定的 Aware 接口,容器会回调对应方法注入容器资源,执行顺序固定:
BeanNameAware.setBeanName():注入 Bean 在容器中的名称。BeanFactoryAware.setBeanFactory():注入 BeanFactory 实例。ApplicationContextAware.setApplicationContext():注入 ApplicationContext 实例(仅限 ApplicationContext 容器)。
四、BeanPostProcessor 前置处理(Pre-Initialization)
容器调用所有注册的 BeanPostProcessor.postProcessBeforeInitialization() 方法。这是 Spring 提供的全局扩展点,允许在 Bean 初始化前修改 Bean 实例(如属性校验、包装对象)。
五、初始化(Initialization)
Bean 执行开发者定义的初始化逻辑,执行顺序严格固定:
@PostConstruct注解方法(JSR-250 标准,优先级最高)。InitializingBean.afterPropertiesSet()接口方法。init-method(通过@Bean(initMethod = "...")或 XML 配置的自定义初始化方法)。
六、BeanPostProcessor 后置处理(Post-Initialization)
容器调用 BeanPostProcessor.postProcessAfterInitialization() 方法。这是 AOP 代理的生成点——Spring 在此判断 Bean 是否需要被代理(如 @Transactional、@Async),若需要则返回 JDK 或 CGLIB 动态代理对象替换原始 Bean。
七、就绪(Ready)
Bean 完全初始化完成,被放入容器的单例池(singletonObjects,一级缓存),可供应用程序正常调用。
八、销毁(Destruction)
当容器关闭时(调用 context.close() 或 JVM 优雅退出),触发销毁逻辑,执行顺序与初始化相反:
@PreDestroy注解方法。DisposableBean.destroy()接口方法。destroy-method(自定义销毁方法)。
关键扩展点速查表
| 扩展点 | 阶段 | 作用 |
|---|---|---|
BeanFactoryPostProcessor |
BeanDefinition 注册后,实例化前 | 修改 Bean 的定义元数据 |
BeanPostProcessor.postProcessBeforeInitialization |
实例化后,初始化前 | 统一修改 Bean 实例 |
@PostConstruct / InitializingBean |
初始化阶段 | 执行自定义初始化逻辑 |
BeanPostProcessor.postProcessAfterInitialization |
初始化后 | AOP 代理生成 |
@PreDestroy / DisposableBean |
销毁阶段 | 释放资源 |
面试高频追问
Q1:AOP 代理在哪一步生成?
A:在 BeanPostProcessor.postProcessAfterInitialization() 阶段。Spring 通过 AbstractAutoProxyCreator 判断 Bean 是否需要被代理,若需要则返回代理对象。
Q2:@PostConstruct 和 InitializingBean 的执行顺序?
A:@PostConstruct 先于 afterPropertiesSet(),afterPropertiesSet() 先于 init-method。
Q3:单例 Bean 和多例 Bean 的生命周期差异?
A:单例 Bean 由容器管理完整生命周期(创建→初始化→销毁);多例 Bean(prototype)容器只负责创建和初始化,不负责销毁,销毁逻辑需由调用方自行管理。
