Spring 扩展点总结与分析
1. 容器启动前扩展
扩展点:ApplicationContextInitializer
作用阶段:Spring 容器刷新(refresh()
)之前。
业务扩展方向:
- 动态激活环境配置(如切换 Profile)。
- 预加载外部资源(如远程配置中心数据)。
- 注册自定义
PropertySource
(扩展配置源)。
代码示例:
public class EnvConfigInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext context) {
System.setProperty("app.mode", "cluster");
}
}
2. Bean 定义扩展
扩展点:BeanDefinitionRegistryPostProcessor
作用阶段:Bean 定义加载后、实例化前。
业务扩展方向:
- 动态注册 Bean:如根据数据库配置生成动态数据源。
- 修改 Bean 定义:调整 Bean 的作用域或属性(如
@Scope
覆盖)。 - 框架集成:MyBatis 通过此接口注册 Mapper 接口的代理类。
代码示例:
public class DynamicBeanRegistrar implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
registry.registerBeanDefinition("customBean", new RootBeanDefinition(CustomService.class));
}
}
// org.mybatis.spring.mapper.MapperScannerConfigurer#postProcessBeanDefinitionRegistry
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware {
private String basePackage;
private ApplicationContext applicationContext;
public void setBasePackage(String basePackage) {
this.basePackage = basePackage;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
//设置其资源加载器为当前的 ApplicationContext
scanner.setResourceLoader(this.applicationContext);
scanner.registerFilters();
//调用 scanner.scan(this.basePackage) 方法,扫描指定的包路径,找到所有符合条件的 Mapper 接口,并将它们注册为 Spring 的 BeanDefinition。
scanner.scan(this.basePackage);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 省略
}
}
3. Bean 实例化扩展
扩展点:BeanPostProcessor
作用阶段:Bean 初始化前后(如 @PostConstruct
执行前后)。
业务扩展方向:
- AOP 代理增强:自动为特定 Bean 生成动态代理(如
@Async
实现)。 - 属性注入校验:检查
@Autowired
字段是否为空。 - 监控埋点:统计 Bean 方法执行耗时。
代码示例:
public class LoggingBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return Proxy.newProxyInstance(bean.getClass().getClassLoader(),
bean.getClass().getInterfaces(), (proxy, method, args) -> {
System.out.println("Method called: " + method.getName());
return method.invoke(bean, args);
});
}
}
public class AsyncAnnotationBeanPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor {
@Override
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
// 创建异步通知器 AsyncAnnotationAdvisor
AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler);
if (this.asyncAnnotationType != null) {
advisor.setAsyncAnnotationType(this.asyncAnnotationType);
}
// 设置代理类型(JDK 动态代理或 CGLIB)
advisor.setProxyTargetClass(this.proxyTargetClass);
this.advisor = advisor;
}
}
4. 生命周期回调
扩展点:InitializingBean
(afterPropertiesSet()
)、DisposableBean
(destroy()
)
作用阶段:Bean 属性注入后、销毁前。
业务扩展方向:
- 资源初始化:数据库连接池启动。
- 优雅停机:释放占用的资源(如线程池关闭)。
代码示例:
public class CacheManager implements InitializingBean, DisposableBean {
@Override
public void afterPropertiesSet() {
initRedisConnection();
}
@Override
public void destroy() {
releaseRedisConnection();
}
}
5. 事件监听扩展
扩展点:ApplicationListener
(监听 ApplicationEvent
)
关键事件:
ContextRefreshedEvent
:容器刷新完成(缓存预热)。ContextClosedEvent
:容器关闭(资源清理)。RequestHandledEvent
:HTTP 请求处理完毕(请求日志统计)。
业务扩展方向:
- 分布式配置热更新:监听配置变更事件。
- 服务状态监控:容器启动后注册到注册中心。
代码示例:
@Component
public class CacheWarmUpListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
loadHotDataToCache();
}
}
6. 条件化装配扩展
扩展点:Condition
(配合 @Conditional
)
作用阶段:Bean 加载条件判断。
业务扩展方向:
- 环境适配:根据操作系统动态加载实现类。
- 功能开关:通过配置中心控制 Bean 是否生效。
代码示例:
public class ClusterModeCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return "cluster".equals(context.getEnvironment().getProperty("app.mode"));
}
}
@Configuration
@Conditional(ClusterModeCondition.class)
public class ClusterConfig { /* 集群模式专用配置 */ }
7. 自定义作用域
扩展点:Scope
(如 @RequestScope
、@SessionScope
)
业务扩展方向:
- Web 请求级缓存:每个 HTTP 请求绑定独立 Bean 实例。
- 分布式会话管理:自定义作用域存储到 Redis。
代码示例:
public class ThreadLocalScope implements Scope {
private ThreadLocal<Map<String, Object>> threadLocal = ThreadLocal.withInitial(HashMap::new);
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
return threadLocal.get().computeIfAbsent(name, k -> objectFactory.getObject());
}
}
8. 类型转换扩展
扩展点:Converter
、GenericConverter
业务扩展方向:
- 复杂对象解析:字符串转枚举、日期格式统一处理。
- API 参数映射:将 HTTP 参数转换为领域对象。
代码示例:
public class StringToUserConverter implements Converter<String, User> {
@Override
public User convert(String source) {
return JSON.parseObject(source, User.class);
}
}
9. Spring Boot 特有扩展
扩展点:ApplicationRunner
、CommandLineRunner
作用阶段:应用启动完成后。
业务扩展方向:
- 初始化任务:数据库脚本检查、静态资源预加载。
- 异步启动:非阻塞执行耗时任务(如消息队列消费者启动)。
代码示例:
@Component
public class DataCheckRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) {
validateDatabaseSchema();
}
}
总结:扩展方向与业务场景
扩展类型 | 典型业务场景 |
---|---|
容器级扩展 | 环境配置预处理、全局资源初始化(如密钥加载) |
Bean 生命周期扩展 | AOP 增强(日志/权限)、资源管理(连接池)、状态监控(如统计 Bean 创建耗时) |
事件驱动扩展 | 分布式配置同步、服务注册/发现、请求链路追踪 |
条件化装配 | 多环境配置隔离(开发/测试/生产)、功能灰度发布 |
自定义作用域 | Web 请求级数据隔离、多租户资源分配 |
Spring Boot 扩展 | 启动任务编排(依赖检查)、命令行参数解析 |
设计原则与最佳实践
- 明确阶段:根据业务需求选择最靠近目标阶段的扩展点(如修改 Bean 定义用
BeanFactoryPostProcessor
而非BeanPostProcessor
)。 - 避免副作用:确保扩展逻辑不影响 Spring 原生生命周期(如
BeanPostProcessor
中避免过早初始化其他 Bean)。 - 性能优先:高频扩展点(如
BeanPostProcessor
)应减少阻塞操作,必要时采用懒加载或异步处理。 - 兼容性:自定义扩展需考虑 Spring 版本差异(如
ApplicationContextInitializer
在 Spring Boot 中的注册方式)。