Spring扩展点

143 阅读4分钟

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实例化完成、属性注入后,分别在以下两个时点执行:

    1. 初始化前postProcessBeforeInitialization()(在@PostConstructInitializingBean.afterPropertiesSet()、自定义init-method之前)。
    2. 初始化后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

实际应用场景

  1. 动态数据源切换:通过BeanPostProcessor在运行时根据注解切换数据源。
  2. 配置加密:通过BeanFactoryPostProcessor解密配置文件中的加密属性。
  3. 接口耗时统计:通过BeanPostProcessor为Service层方法添加耗时监控。
  4. 全局缓存预热:监听ContextRefreshedEvent,在容器启动后加载缓存。
  5. 自定义作用域:通过Scope接口和BeanPostProcessor实现线程级或会话级Bean作用域。

掌握这些扩展点的调用时机,能够帮助开发者在Spring容器的不同阶段精准插入自定义逻辑,实现高度灵活的业务需求。