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

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. 生命周期回调

扩展点InitializingBeanafterPropertiesSet())、DisposableBeandestroy()
作用阶段: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. 类型转换扩展

扩展点ConverterGenericConverter
业务扩展方向

  • 复杂对象解析:字符串转枚举、日期格式统一处理。
  • API 参数映射:将 HTTP 参数转换为领域对象。
    代码示例
public class StringToUserConverter implements Converter<String, User> {
    @Override
    public User convert(String source) {
        return JSON.parseObject(source, User.class);
    }
}

9. Spring Boot 特有扩展

扩展点ApplicationRunnerCommandLineRunner
作用阶段:应用启动完成后。
业务扩展方向

  • 初始化任务:数据库脚本检查、静态资源预加载。
  • 异步启动:非阻塞执行耗时任务(如消息队列消费者启动)。

代码示例

@Component
public class DataCheckRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) {
        validateDatabaseSchema();
    }
}

总结:扩展方向与业务场景

扩展类型典型业务场景
容器级扩展环境配置预处理、全局资源初始化(如密钥加载)
Bean 生命周期扩展AOP 增强(日志/权限)、资源管理(连接池)、状态监控(如统计 Bean 创建耗时)
事件驱动扩展分布式配置同步、服务注册/发现、请求链路追踪
条件化装配多环境配置隔离(开发/测试/生产)、功能灰度发布
自定义作用域Web 请求级数据隔离、多租户资源分配
Spring Boot 扩展启动任务编排(依赖检查)、命令行参数解析

设计原则与最佳实践

  1. 明确阶段:根据业务需求选择最靠近目标阶段的扩展点(如修改 Bean 定义用 BeanFactoryPostProcessor 而非 BeanPostProcessor)。
  2. 避免副作用:确保扩展逻辑不影响 Spring 原生生命周期(如 BeanPostProcessor 中避免过早初始化其他 Bean)。
  3. 性能优先:高频扩展点(如 BeanPostProcessor)应减少阻塞操作,必要时采用懒加载或异步处理。
  4. 兼容性:自定义扩展需考虑 Spring 版本差异(如 ApplicationContextInitializer 在 Spring Boot 中的注册方式)。

http://www.kler.cn/a/589210.html

相关文章:

  • 【论文笔记】FFA-Net: Feature Fusion Attention Network for Single Image Dehazing
  • Spring MVC源码分析の请求处理流程
  • 从过拟合到强化学习:机器学习核心知识全解析
  • R 语言科研绘图 --- 密度图-汇总
  • C/C++基数排序(Radix Sort) 的排序算法。
  • 深入理解TCP/IP网络模型及Linux网络管理
  • Solidity基础 -- 哈希算法
  • C++ QT零基础教学(二)
  • tomato靶场通关攻略
  • Leetcode-131.Palindrome Partitioning [C++][Java]
  • ST的全新STM32U3微控制器(MCU)简析
  • 视频推拉流EasyDSS案例分析:互联网直播/点播技术与平台创新应用
  • 【PyTorch教学】pytorch 基本语法
  • 消息队列 Kafka、RocketMQ、RabbitMQ 对比与分析
  • 蓝桥杯备考:图论之Prim算法
  • 分类操作-06.根据id删除分类
  • python 打印阳历对应的日农历时间
  • .gitignore 文件用于 Git 应忽略的文件夹的格式
  • SNX币合规交易突破 XBIT去中心化交易所引领DEX安全新范式
  • Notepad++插件:快捷选择成对括号之间的内容