选择 Spring 扩展点时先问“我要改变哪个阶段”。注册新配方、修改已有配方、控制对象创建、包装实例和响应事件是五种不同责任。
Table of contents
Open Table of contents
运行 Registrar 实验
FeatureRegistrar下载程序化注册一个 BeanDefinition:
mvn -Dtest=SpringSourceLabTest#registrarAddsABeanDefinition test
Registrar 接收导入配置的注解元数据和 Registry,适合根据声明式配置批量注册定义。它不应直接创建业务单例。
扩展点选择表
| 目标 | 首选扩展点 |
|---|---|
| 程序化新增定义 | ImportBeanDefinitionRegistrar |
| 修改定义元数据 | BeanFactoryPostProcessor |
| 创建复杂或代理对象 | FactoryBean |
| 初始化前后包装 Bean | BeanPostProcessor |
| 容器完成后的业务通知 | ApplicationListener |
FactoryBean 本身是 Bean,getObject() 产物才是普通 getBean(name) 返回的对象;用 &name 才取得 FactoryBean。这个命名协议是排查类型不符时的重要线索。
顺序和提前实例化风险
工厂级处理器通过 PriorityOrdered、Ordered 和普通三组执行。BeanPostProcessor 也有顺序,但不要依赖相同优先级下的碰巧注册顺序。
后置处理器创建期间调用 getBean 可能让目标过早实例化,错过后续处理器。扩展代码应该只读取必要元数据,并通过测试断言目标 Bean 的最终运行类型。
事件不是可靠消息队列
默认 Spring 应用事件在发布线程同步执行。慢 Listener 会拖慢发布者,异常也可能向上传播。异步事件需要明确执行器、上下文传播和失败处理;跨进程可靠事件应使用事务消息或 Outbox 等机制。
下一步
阅读AOP 代理创建与调用链,查看 BeanPostProcessor 如何把目标对象包装成拦截器链。