当前位置: 首页 > news >正文

Spring Bean 生命周期高阶用法:从回调到框架级扩展

Spring Bean 生命周期高阶用法:从回调到框架级扩展

把 Spring 容器当作一条「装配流水线」,在 7 个标准阶段之间任意「加戏」,即可零侵入地完成动态代理、多租户装配、优雅停机、第三方库接管等高级需求。


一、生命周期全景图(精简版)

阶段回调/扩展点典型用途
实例化前InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation跳过默认构造,返回代理
实例化后InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation决定是否继续属性填充
属性填充后BeanPostProcessor#postProcessProperties动态注入(如 @Value 解析增强)
初始化前BeanPostProcessor#postProcessBeforeInitialization日志、监控、AOP
初始化阶段@PostConstructInitializingBean#afterPropertiesSetinit-method业务初始化
初始化后BeanPostProcessor#postProcessAfterInitialization代理包装、缓存代理
销毁阶段@PreDestroyDisposableBean#destroydestroy-method资源释放
销毁前额外钩子DestructionAwareBeanPostProcessor#postProcessBeforeDestruction优雅停机、线程池关闭

二、6 个官方扩展点速查

接口/注解说明代码片段
InstantiationAwareBeanPostProcessor控制是否实例化/提前暴露代理见「实战 1」
SmartInstantiationAwareBeanPostProcessor解决循环依赖、选择构造器determineCandidateConstructors
BeanPostProcessor通用前置/后置处理与 Bean 实例一起注册
DestructionAwareBeanPostProcessor销毁前钩子关闭线程池、释放锁
InitializingBean / DisposableBean传统接口与容器深度集成
@PostConstruct / @PreDestroyJSR-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 生命周期变成「乐高流水线」:
实例化前换零件、初始化后加装饰、销毁前做清理——
高级玩法,不过如此。

http://www.xdnf.cn/news/1371295.html

相关文章:

  • Java基础第5天总结(final关键字,枚举,抽象类)
  • CVPR自适应卷积的高效实现:小核大感受野提升复杂场景下图像重建精度
  • vue新增用户密码框自动将当前用户的密码自动填充的问题
  • 高校党建系统设计与实现(代码+数据库+LW)
  • 嵌入式配置数据序列化:自定义 TLV vs nanopb
  • 深度学习篇---LeNet-5
  • 1Panel命令
  • 100种交易系统(6)均线MA识别信号与杂音
  • 深度学习----由手写数字识别案例来认识PyTorch框架
  • Python实现RANSAC进行点云直线、平面、曲面、圆、球体和圆柱拟合
  • Il2CppInspector 工具linux编译使用
  • 设计模式之命令模式
  • Vuex 和 Pinia 各自的优点
  • Linux之SELinux 概述、SSH 密钥登录、服务器初始化
  • 利用AI进行ArcGISPro进行数据库的相关处理?
  • Java数据结构速成【1】
  • 原则性 单一职责原则,第一性原则和ACID原则 : 安全/学习/节约
  • 从双重检查锁定的设计意图、锁的作用、第一次检查提升性能的原理三个角度,详细拆解单例模式的逻辑
  • Markdown学习笔记(4)
  • 矩阵微积分的链式法则(chain rule)
  • 在 Android Studio 中修改 APK 启动图标(2025826)
  • 从线到机:AI 与多模态交互如何重塑 B 端与 App 界面设计
  • 【RAGFlow代码详解-23】聊天系统架构
  • 【LeetCode 热题 100】75. 颜色分类——双指针
  • PWM控制实现呼吸灯
  • 家庭财务规划与投资系统的设计与实现(代码+数据库+LW)
  • Linux SSH 基于密钥交换的自动登录:原理与配置指南
  • (Arxiv-2024)VideoMaker:零样本定制化视频生成,依托于视频扩散模型的内在力量
  • 进程管理详解
  • 如何将视频从安卓设备传输到Mac?