Spring Bean生命周期的核心流程

结论先行

Spring Bean的生命周期由IoC容器管理,核心流程为“实例化 → 属性注入 → 初始化 → 使用 → 销毁”,通过扩展点(如BeanPostProcessor)和标准接口(如InitializingBean)实现精细控制。以下是完整内容:

文章持续更新,可以微信搜一搜「 半个脑袋儿 」第一时间阅读


一、核心流程图
1. 实例化 → 2. 属性注入 → 3. Aware回调 → 4. 初始化前处理 → 5. 初始化 → 6. 初始化后处理 → 7. 使用 → 8. 销毁前处理 → 9. 销毁  

二、详细阶段说明
1. 实例化(Instantiation)
  • 动作:通过反射调用构造函数或工厂方法创建Bean实例(此时对象属性未赋值)。
  • 扩展点
    • InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
      • 作用:可返回自定义对象(如Mock对象),跳过Spring默认实例化。
2. 属性注入(Population)
  • 动作:通过Setter、构造器或字段注入依赖(如@Autowired@Value)。
  • 扩展点
    • InstantiationAwareBeanPostProcessor.postProcessProperties()
      • 作用:动态修改注入的属性值(如解密敏感配置)。
3. Aware接口回调
  • 动作:若Bean实现Aware接口,容器自动注入资源:
    • BeanNameAware:设置Bean的名称。
    • ApplicationContextAware:注入ApplicationContext引用(可用于手动获取其他Bean)。
4. 初始化前处理(Before Initialization)
  • 动作
    1. 执行@PostConstruct注解的方法。
    2. 调用BeanPostProcessor.postProcessBeforeInitialization()
  • 典型用途:数据预热、依赖校验。
5. 初始化(Initialization)
  • 动作顺序
    1. 调用InitializingBean.afterPropertiesSet()(Spring接口)。
    2. 执行自定义init-method(通过XML或@Bean(initMethod="...")配置)。
6. 初始化后处理(After Initialization)
  • 动作
    • 调用BeanPostProcessor.postProcessAfterInitialization()
    • AOP代理生成:如@Transactional@Async在此阶段生效。
7. 使用阶段(In Use)
  • 注意:若Bean被AOP代理,业务代码实际调用的是代理对象。
8. 销毁前处理(Before Destruction)
  • 动作
    • 执行@PreDestroy注解的方法。
9. 销毁(Destruction)
  • 动作顺序
    1. 调用DisposableBean.destroy()(Spring接口)。
    2. 执行自定义destroy-method

三、关键扩展点总结
扩展点/接口作用阶段核心功能
InstantiationAwareBeanPostProcessor实例化、属性注入拦截实例化、动态修改属性值(如解密敏感字段)
BeanPostProcessor初始化前后AOP代理生成、全局预处理(如日志埋点)
Aware接口Aware回调阶段获取容器资源(如Bean名称、ApplicationContext)
@PostConstruct/@PreDestroy初始化前/销毁前无侵入式初始化和清理(如缓存预热、资源释放)
InitializingBean/DisposableBean初始化/销毁阶段Spring原生生命周期接口(强耦合,慎用)

四、实战场景与代码示例
场景1:动态解密敏感配置
public class DecryptBeanPostProcessor implements InstantiationAwareBeanPostProcessor {  
    @Override  
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String name) {  
        // 解密带有@Encrypted注解的字段  
        Field[] fields = bean.getClass().getDeclaredFields();  
        for (Field field : fields) {  
            if (field.isAnnotationPresent(Encrypted.class)) {  
                field.setAccessible(true);  
                String value = (String) pvs.getPropertyValue(field.getName()).getValue();  
                field.set(bean, decrypt(value)); // 解密逻辑  
            }  
        }  
        return pvs;  
    }  
}  
场景2:AOP代理导致内部调用失效
  • 问题:在Bean内部调用this.method()时,@Transactional不生效。
  • 原因:内部调用绕过代理对象,直接调用原始方法。
  • 解决:通过AopContext获取代理对象:
    public void save() {  
        ((UserService) AopContext.currentProxy()).update(); // 通过代理对象调用  
    }  
    
场景3:资源释放
@Service  
public class DataSourceService {  
    @PreDestroy  
    public void cleanup() {  
        dataSource.close(); // 关闭数据库连接池  
    }  
}  

五、常见问题解答
  1. 循环依赖如何解决?

    • Setter注入:通过三级缓存(提前暴露半成品Bean)。
    • 构造器注入:无法解决,直接报错。
  2. 为什么AOP代理在初始化后生成?

    • 确保所有依赖注入完成,避免代理对象因属性未注入而失效。
  3. 销毁方法不执行怎么办?

    • 检查点:确保Bean是单例作用域,且容器正常关闭(如调用context.close())。

总结

Spring Bean生命周期是IoC容器的核心机制,本质是“标准化流水线 + 扩展点开放”的设计。掌握以下两点即可应对大多数场景:

  1. 流程顺序:实例化 → 属性注入 → 初始化 → 代理生成 → 销毁。
  2. 扩展点选择
    • 干预实例化:InstantiationAwareBeanPostProcessor
    • 干预初始化:BeanPostProcessor
    • 资源管理:@PostConstruct/@PreDestroy
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值