Spring Bean 生命周期高阶用法:从回调到框架级扩展
Spring Bean 生命周期高阶用法:从回调到框架级扩展
把 Spring 容器当作一条「装配流水线」,在 7 个标准阶段之间任意「加戏」,即可零侵入地完成动态代理、多租户装配、优雅停机、第三方库接管等高级需求。
一、生命周期全景图(精简版)
阶段 | 回调/扩展点 | 典型用途 |
---|---|---|
实例化前 | InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation | 跳过默认构造,返回代理 |
实例化后 | InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation | 决定是否继续属性填充 |
属性填充后 | BeanPostProcessor#postProcessProperties | 动态注入(如 @Value 解析增强) |
初始化前 | BeanPostProcessor#postProcessBeforeInitialization | 日志、监控、AOP |
初始化阶段 | @PostConstruct → InitializingBean#afterPropertiesSet → init-method | 业务初始化 |
初始化后 | BeanPostProcessor#postProcessAfterInitialization | 代理包装、缓存代理 |
销毁阶段 | @PreDestroy → DisposableBean#destroy → destroy-method | 资源释放 |
销毁前额外钩子 | DestructionAwareBeanPostProcessor#postProcessBeforeDestruction | 优雅停机、线程池关闭 |
二、6 个官方扩展点速查
接口/注解 | 说明 | 代码片段 |
---|---|---|
InstantiationAwareBeanPostProcessor | 控制是否实例化/提前暴露代理 | 见「实战 1」 |
SmartInstantiationAwareBeanPostProcessor | 解决循环依赖、选择构造器 | determineCandidateConstructors |
BeanPostProcessor | 通用前置/后置处理 | 与 Bean 实例一起注册 |
DestructionAwareBeanPostProcessor | 销毁前钩子 | 关闭线程池、释放锁 |
InitializingBean / DisposableBean | 传统接口 | 与容器深度集成 |
@PostConstruct / @PreDestroy | JSR-250 注解 | 零侵入 |
三、3 个高阶实战套路
1️⃣ 动态代理:在实例化阶段直接返回子类
public class RpcProxyCreator implements InstantiationAwareBeanPostProcessor {@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {// 只对接口生成代理if (beanClass.isInterface() && beanClass.isAnnotationPresent(RpcClient.class)) {return Proxy.newProxyInstance(beanClass.getClassLoader(),new Class[]{beanClass},new RpcInvocationHandler());}return null; // 返回 null,继续默认流程}
}
效果:接口无需实现类,容器直接注入代理对象。
2️⃣ 多租户 Bean:实例化后动态注入租户字段
public class TenantBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {if (bean instanceof TenantAware) {((TenantAware) bean).setTenantId(TenantContext.get());}return bean;}
}
效果:同一个 TenantService
在不同租户下拥有独立字段值。
3️⃣ 优雅停机:线程池安全关闭
public class ExecutorShutdownProcessor implements DestructionAwareBeanPostProcessor {@Overridepublic void postProcessBeforeDestruction(Object bean, String beanName) {if (bean instanceof ExecutorService) {ExecutorService es = (ExecutorService) bean;es.shutdown();try { es.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException ie) { es.shutdownNow(); }}}
}
效果:容器关闭时,所有线程池优雅终止,避免任务丢失。
四、组合模板:一条 Bean 同时享受所有钩子
@Component
public class MyBean implements InitializingBean, DisposableBean {@PostConstructpublic void postConstruct() { /* 注解初始化 */ }@Overridepublic void afterPropertiesSet() { /* 接口初始化 */ }@PreDestroypublic void preDestroy() { /* 注解销毁 */ }@Overridepublic void destroy() { /* 接口销毁 */ }
}
执行顺序(Spring 5.3+)
① postProcessBeforeInitialization
② @PostConstruct
③ afterPropertiesSet
④ postProcessAfterInitialization
⑤ 业务运行
⑥ @PreDestroy
⑦ destroy
⑧ postProcessBeforeDestruction
五、常见误区 & 对策
误区 | 正解 |
---|---|
在 Bean 内部直接 new Thread() | 用 ExecutorService 并注册销毁钩子 |
实现 InitializingBean 导致无法单元测试 | 改用 @PostConstruct ,更易 Mock |
循环依赖无法解决 | 实现 SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference |
六、一句话总结
掌握 InstantiationAware、BeanPostProcessor、DestructionAware 三大接口,
就可以把 Spring Bean 生命周期变成「乐高流水线」:
实例化前换零件、初始化后加装饰、销毁前做清理——
高级玩法,不过如此。