您的位置:首页 > 财经 > 产业 > 网站建设莱州哪家强?_湖南网络推广排名_谷粉搜索谷歌搜索_谷歌浏览器下载手机版

网站建设莱州哪家强?_湖南网络推广排名_谷粉搜索谷歌搜索_谷歌浏览器下载手机版

2025/3/28 14:52:42 来源:https://blog.csdn.net/xiaolingting/article/details/146265339  浏览:    关键词:网站建设莱州哪家强?_湖南网络推广排名_谷粉搜索谷歌搜索_谷歌浏览器下载手机版
网站建设莱州哪家强?_湖南网络推广排名_谷粉搜索谷歌搜索_谷歌浏览器下载手机版

在这里插入图片描述


一、 接口定义

SmartInitializingSingleton 是 Spring 框架提供的一个 单例 Bean 全局初始化回调接口,用于在 所有非延迟单例 Bean 初始化完成后 执行自定义逻辑。
核心方法

public interface SmartInitializingSingleton {void afterSingletonsInstantiated();
}

二、 触发时机

  • 执行阶段:所有非延迟单例 Bean 的实例化、依赖注入及 InitializingBean/@PostConstruct/init-method 初始化完成后触发。
  • 设计意义:确保全局 Bean 依赖已就绪,避免早期初始化的副作用(如依赖未完全加载导致空指针)。

三、 实现步骤

步骤 1:创建实现类

@Component
public class GlobalInitializer implements SmartInitializingSingleton {@Overridepublic void afterSingletonsInstantiated() {// 所有单例 Bean 初始化完成后执行System.out.println("执行全局初始化逻辑...");}
}

步骤 2:注册为 Spring Bean

  • 通过 @Component@Bean 或 XML 配置注册。
  • 注意:实现类本身必须是 单例且非延迟加载 的 Bean。

四、 与其他初始化机制对比

特性SmartInitializingSingletonInitializingBean/@PostConstructBeanPostProcessor
执行范围所有非延迟单例 Bean 初始化完成后执行一次每个 Bean 初始化完成后执行一次每个 Bean 初始化前后执行
适用场景全局初始化逻辑(如缓存预热)单个 Bean 的初始化逻辑(如字段校验)干预 Bean 创建过程(如代理增强)
执行顺序最晚(所有单例就绪后)较早(Bean 初始化阶段)分散在 Bean 生命周期各阶段
多例 Bean 支持不适用支持支持

五、 使用场景

场景示例
缓存预热在服务启动时预加载热点数据到 Redis 或本地缓存。
动态配置初始化加载数据库中的动态配置,并应用到运行时环境。
启动后台任务初始化定时任务、消息队列消费者或异步线程池。
资源依赖校验校验所有单例 Bean 的依赖关系是否完整(如检查第三方服务连通性)。
框架集成扩展在 Spring Cloud 中定制 RestTemplate,或在 XXL-JOB 中注册执行器。

1. 缓存预热

场景描述
在服务启动时,预加载热点数据到本地或分布式缓存(如 Redis),避免首次请求时因缓存未命中导致的性能损耗。
实现逻辑

  • 依赖所有单例 Bean(如数据库连接池、缓存客户端)初始化完成。
  • 执行预热逻辑(如从数据库查询高频数据并写入缓存)。

示例

@Component
public class CacheWarmup implements SmartInitializingSingleton {@Autowiredprivate CacheService cacheService;@Autowiredprivate DataRepository dataRepository;@Overridepublic void afterSingletonsInstantiated() {List<HotData> hotData = dataRepository.findHotData();cacheService.batchSet(hotData);}
}

2. 动态配置初始化

场景描述
从数据库或配置中心加载动态配置(如开关、阈值),并应用到运行时环境。
实现逻辑

  • 确保依赖的配置解析器、数据源等 Bean 已初始化。
  • 加载配置并设置到全局变量或 Spring 上下文。

示例

@Component
public class DynamicConfigLoader implements SmartInitializingSingleton {@Autowiredprivate ConfigService configService;@Overridepublic void afterSingletonsInstantiated() {configService.loadRemoteConfig();System.setProperty("feature.flag", configService.getFeatureFlag());}
}

3. 后台任务启动

场景描述
初始化定时任务、消息队列消费者或异步线程池,避免任务启动时依赖未就绪。
实现逻辑

  • 确保任务依赖的 Bean(如线程池、MQ 客户端)已初始化。
  • 启动定时任务或消息监听器。

示例

@Component
public class TaskInitializer implements SmartInitializingSingleton {@Autowiredprivate ScheduledExecutorService executor;@Autowiredprivate OrderSyncTask orderSyncTask;@Overridepublic void afterSingletonsInstantiated() {executor.scheduleAtFixedRate(orderSyncTask, 0, 1, TimeUnit.HOURS);}
}

4. 资源依赖校验

场景描述
校验所有单例 Bean 的依赖是否完整,或检测第三方服务连通性。
实现逻辑

  • 在全局 Bean 初始化完成后,检查关键资源(如数据库连接、外部 API)是否可用。
  • 若校验失败,抛出异常阻止服务启动。

示例

@Component
public class DependencyChecker implements SmartInitializingSingleton {@Autowiredprivate ThirdPartyService thirdPartyService;@Overridepublic void afterSingletonsInstantiated() {if (!thirdPartyService.isAvailable()) {throw new IllegalStateException("第三方服务不可用");}}
}

5. 框架集成扩展

场景描述
在 Spring 生态中扩展框架功能,如注册事件监听器、初始化 RPC 服务或任务执行器。
实现逻辑

  • 扫描特定注解(如 @XxlJob@EventListener)标记的方法。
  • 注册任务处理器或事件监听器到框架。

参考案例

  • XXL-JOB 任务注册
    public class XxlJobSpringExecutor extends XxlJobExecutor implements SmartInitializingSingleton {@Overridepublic void afterSingletonsInstantiated() {// 扫描 @XxlJob 注解的方法并注册任务initJobHandlers();// 启动 Netty 服务端super.start();}
    }
    
  • Spring 事件监听器注册
    EventListenerMethodProcessor 类通过此接口处理 @EventListener 注解的方法。
    public class EventListenerMethodProcessorimplements SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor {//省略}
    
    在这里插入图片描述
  • Spring 注册定时任务到任务调度器
    ScheduledAnnotationBeanPostProcessor 类通过此接口处理 @Scheduled 注解的方法。
    public class ScheduledAnnotationBeanPostProcessorimplements ScheduledTaskHolder, MergedBeanDefinitionPostProcessor, DestructionAwareBeanPostProcessor,Ordered, EmbeddedValueResolverAware, BeanNameAware, BeanFactoryAware, ApplicationContextAware,SmartInitializingSingleton, ApplicationListener<ContextRefreshedEvent>, DisposableBean {// 省略}
    
    在这里插入图片描述

6. 全局状态初始化

场景描述
初始化全局状态(如计数器、分布式锁管理器),确保依赖的 Bean 已就绪。
示例

@Component
public class GlobalStateInitializer implements SmartInitializingSingleton {@Autowiredprivate DistributedLockManager lockManager;@Overridepublic void afterSingletonsInstantiated() {lockManager.initLocks("order_lock", "inventory_lock");}
}

六、 典型问题与解决方案

问题 1:事件监听器注册顺序冲突

  • 现象@EventListenerSmartInitializingSingleton 阶段注册,若其他 Bean 在 @PostConstruct 中发布事件,可能导致事件丢失。
  • 解决:在 afterSingletonsInstantiated() 中启动消息消费等异步逻辑,确保监听器已就绪。

问题 2:多 Bean 初始化顺序控制

  • 需求:强制某些 Bean 优先初始化。
  • 方案:结合 @DependsOnBeanDefinitionRegistryPostProcessor 动态调整 Bean 定义。

七、源码执行流程

  1. 容器启动AbstractApplicationContext.refresh() 进入 finishBeanFactoryInitialization() 阶段。
  2. 初始化单例DefaultListableBeanFactory.preInstantiateSingletons() 初始化所有非延迟单例 Bean。
  3. 回调触发:遍历所有单例 Bean,调用实现 SmartInitializingSingleton 的 Bean 的 afterSingletonsInstantiated()
    // DefaultListableBeanFactory.java
    for (String beanName : beanNames) {Object bean = getBean(beanName);if (bean instanceof SmartInitializingSingleton) {smartSingletons.add((SmartInitializingSingleton) bean);}
    }
    for (SmartInitializingSingleton singleton : smartSingletons) {singleton.afterSingletonsInstantiated();
    }
    

八、 最佳实践

  • 避免阻塞操作afterSingletonsInstantiated() 应快速执行,避免阻塞容器启动。
  • 结合 @Conditional:根据条件动态启用初始化逻辑(如仅在生产环境预热缓存)。
  • 单元测试验证:通过 ApplicationContext 断言初始化逻辑的执行结果。

总结

  • SmartInitializingSingleton 是 Spring 中用于 全局单例初始化后置处理 的关键接口,适用于依赖全量 Bean 就绪的场景。其设计弥补了 InitializingBean 在全局性、顺序控制上的不足,是框架扩展与业务初始化的高效工具。

  • SmartInitializingSingleton 的核心价值在于其 执行时机的全局性,适用于以下特征场景:

    1. 依赖全量 Bean 就绪:需要所有非延迟单例 Bean 初始化完成后再执行逻辑。
    2. 一次性操作:如服务启动时的初始化动作,避免重复执行。
    3. 框架扩展:与 Spring 生命周期深度集成,补充框架功能(如任务注册、事件监听)。
    4. 规避早期副作用:防止在 Bean 未完全初始化时触发意外行为(如空指针)。

附:源码

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com