Spring IOC容器的扩展点包括BeanFactoryPostProcessor(修改Bean定义)、BeanPostProcessor(初始化干预)、Aware接口(感知容器)、生命周期接口(InitializingBean/DisposableBean)及事件监听,支持在容器各阶段插入自定义逻辑。
1. BeanFactoryPostProcessor
调用时机:
- 阶段:容器启动阶段(
refresh()方法内)。 - 触发点:在 Bean定义(BeanDefinition)加载完成之后、Bean实例化之前。
- 执行顺序:可通过
Ordered接口或@Order注解定义多个BeanFactoryPostProcessor的执行顺序。
应用场景:
- 修改Bean定义:动态调整Bean的元数据(如修改属性值、添加属性)。
- 占位符替换:解析配置文件中的
${...}占位符(如PropertySourcesPlaceholderConfigurer)。 - 动态注册Bean:通过编程方式向容器注册新的Bean(如动态数据源配置)。
- 配置加密:解密配置文件中的敏感信息(如数据库密码)。
示例:
@Component
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
BeanDefinition beanDef = beanFactory.getBeanDefinition("dataSource");
beanDef.getPropertyValues().add("password", "decrypted-password");
}
}
2. BeanPostProcessor
调用时机:
-
阶段:Bean实例化与初始化阶段。
-
触发点:在 Bean实例化完成、属性注入后,分别在以下两个时点执行:
- 初始化前:
postProcessBeforeInitialization()(在@PostConstruct、InitializingBean.afterPropertiesSet()、自定义init-method之前)。 - 初始化后:
postProcessAfterInitialization()(在上述初始化方法之后)。
- 初始化前:
应用场景:
- AOP代理生成:为Bean生成动态代理(如
AnnotationAwareAspectJAutoProxyCreator)。 - 事务管理:为方法添加事务拦截逻辑(如
InfrastructureAdvisorAutoProxyCreator)。 - 自定义注解处理:解析Bean上的注解并注入逻辑(如
@Autowired、@Resource)。 - 性能监控:在方法调用前后插入埋点逻辑(如统计方法耗时)。
示例:
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (bean instanceof MyService) {
System.out.println("Before initializing: " + beanName);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof MyService) {
System.out.println("After initializing: " + beanName);
}
return bean;
}
}
3. Aware系列接口
调用时机:
-
阶段:Bean实例化与初始化阶段。
-
触发点:在 属性注入之后、BeanPostProcessor前置处理之前。
-
常见接口:
BeanNameAware:获取Bean的名称。BeanFactoryAware:获取BeanFactory实例。ApplicationContextAware:获取ApplicationContext实例。EnvironmentAware:获取环境变量配置。
应用场景:
- 访问容器基础设施:在Bean中直接使用容器对象(如手动获取其他Bean)。
- 动态决策:根据环境变量或容器状态调整Bean行为。
示例:
@Component
public class MyService implements ApplicationContextAware {
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext context) {
this.context = context;
}
public void useContext() {
OtherBean otherBean = context.getBean(OtherBean.class);
// ...
}
}
4. InitializingBean与DisposableBean
调用时机:
- InitializingBean:在 BeanPostProcessor前置处理之后,调用
afterPropertiesSet()方法。 - DisposableBean:在 容器关闭时,调用
destroy()方法(单例Bean)。
应用场景:
- 资源初始化:如数据库连接、线程池启动。
- 资源释放:如关闭文件句柄、释放网络连接。
示例:
@Component
public class MyResource implements InitializingBean, DisposableBean {
@Override
public void afterPropertiesSet() {
// 初始化资源(如建立数据库连接)
}
@Override
public void destroy() {
// 释放资源(如关闭连接)
}
}
5. 自定义初始化/销毁方法
调用时机:
- 初始化方法:在
InitializingBean.afterPropertiesSet()之后执行(通过@Bean(initMethod="...")或XML配置)。 - 销毁方法:在
DisposableBean.destroy()之后执行(通过@Bean(destroyMethod="...")或XML配置)。
应用场景:
- 替代接口:避免实现Spring特定接口(保持代码纯净)。
- 第三方库集成:控制非Spring管理的对象的生命周期(如遗留代码)。
示例:
@Bean(initMethod = "start", destroyMethod = "stop")
public DataSource dataSource() {
return new HikariDataSource();
}
6. 事件监听(ApplicationListener)
调用时机:
-
阶段:容器就绪阶段、关闭阶段。
-
事件类型:
ContextRefreshedEvent:容器刷新完成。ContextClosedEvent:容器关闭。RequestHandledEvent(Web环境):HTTP请求处理完成。
应用场景:
- 启动后任务:容器就绪后执行初始化任务(如缓存预热)。
- 资源清理:容器关闭时释放全局资源。
- 监控与日志:记录容器生命周期事件。
示例:
@Component
public class StartupListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// 容器启动后执行(如加载静态数据)
}
}
扩展点的执行顺序总结
1. BeanFactoryPostProcessor → 修改Bean定义
2. Bean实例化 → 构造函数调用
3. 属性注入 → 依赖注入完成
4. Aware接口回调 → Bean感知容器
5. BeanPostProcessor.postProcessBeforeInitialization → 初始化前处理
6. @PostConstruct → 自定义初始化前逻辑
7. InitializingBean.afterPropertiesSet → Spring提供的初始化
8. 自定义init-method → 用户定义的初始化
9. BeanPostProcessor.postProcessAfterInitialization → 初始化后处理(如AOP代理)
10. 容器就绪 → ContextRefreshedEvent
11. 容器关闭 → @PreDestroy → DisposableBean.destroy → 自定义destroy-method
实际应用场景
- 动态数据源切换:通过
BeanPostProcessor在运行时根据注解切换数据源。 - 配置加密:通过
BeanFactoryPostProcessor解密配置文件中的加密属性。 - 接口耗时统计:通过
BeanPostProcessor为Service层方法添加耗时监控。 - 全局缓存预热:监听
ContextRefreshedEvent,在容器启动后加载缓存。 - 自定义作用域:通过
Scope接口和BeanPostProcessor实现线程级或会话级Bean作用域。
掌握这些扩展点的调用时机,能够帮助开发者在Spring容器的不同阶段精准插入自定义逻辑,实现高度灵活的业务需求。