欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 幼教 > 【Spring】关于CommandLineRunner 和 SmartInitializingSingleton

【Spring】关于CommandLineRunner 和 SmartInitializingSingleton

2025/2/27 12:16:24 来源:https://blog.csdn.net/qq_36634055/article/details/141030286  浏览:    关键词:【Spring】关于CommandLineRunner 和 SmartInitializingSingleton

昨天扯到了CommandLineRunner ,今天出来个SmartInitializingSingleton

CommandLineRunnerSmartInitializingSingleton 在Spring框架中都用于在应用程序启动后执行某些初始化逻辑,但它们的触发时机、使用场景和设计目的有很大的不同。下面以大白话的形式解释两者的区别:

CommandLineRunner

想象你正在筹备一个派对,派对还没开始,你就想先播放一些音乐来营造氛围。CommandLineRunner就像你派对开始前的DJ,它一上来就直接放音乐,不等人到齐。也就是说,CommandLineRunner在Spring应用完全启动后立即执行,它的主要任务是做一些启动后的初始化工作,比如打印一些信息到控制台,或者做一些简单的数据导入等。它不关心其他的Bean是否已经完全初始化,只要Spring容器已经启动,它就开始干活。

SmartInitializingSingleton

SmartInitializingSingleton更像是你派对上的总策划,他要等到所有的宾客都到场,一切都准备妥当之后,才开始他的工作。这意味着实现SmartInitializingSingleton接口的Bean会在所有单例Bean实例化完成后执行其afterSingletonsInstantiated()方法。它更适合那些需要在所有其他Bean都准备就绪之后才能进行的初始化逻辑,比如依赖于其他服务的状态检查、注册监听器等。

总结

  • 触发时机CommandLineRunner在所有Bean定义加载后立即执行,而SmartInitializingSingleton在所有单例Bean实例化完成后执行。
  • 依赖关系CommandLineRunner不依赖于其他Bean的初始化状态,而SmartInitializingSingleton可能依赖于其他Bean的状态。
  • 使用场景CommandLineRunner适用于那些需要在应用启动后立即执行的简单任务,而SmartInitializingSingleton适用于那些需要在所有服务Bean都准备就绪后执行的复杂初始化逻辑。

简单来说,CommandLineRunner是“派对刚开始就上场的DJ”,而SmartInitializingSingleton是“派对一切准备就绪后的总策划”。两者各有侧重,根据你的应用需求选择合适的一个或组合使用。

  • CommandLineRunner在容器启动后立即执行,此时单例Bean可能已经实例化,但不一定完全初始化,尤其是那些依赖于复杂初始化逻辑的Bean。
  • SmartInitializingSingleton则是在所有单例Bean实例化并且初始化完成之后执行,这意味着它依赖于所有其他单例Bean的状态。

使用场景示例:CommandLineRunner

CommandLineRunner接口通常用于执行一些简单的初始化任务,比如数据库的初始化、数据填充等,这些任务通常不需要依赖于其他Bean的完全初始化状态。下面是一个使用CommandLineRunner的示例:

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;@Component
public class MyCommandLineRunner implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {System.out.println("Application started, executing CommandLineRunner...");// 这里可以执行一些简单的初始化逻辑,例如数据填充// 注意:在多实例化环境(非单例)中,可能需要添加同步处理// 示例:填充数据库// userRepository.save(new User("John", "xxxxxx@example.com"));System.out.println("CommandLineRunner finished.");}
}

在这个示例中,MyCommandLineRunner实现了CommandLineRunner接口,它的run方法将在Spring容器启动后立即执行。注意,这个方法在Spring容器中所有单例Bean实例化之后,但在所有Bean完全初始化之前执行。

使用场景示例:SmartInitializingSingleton

SmartInitializingSingleton接口用于那些需要在所有单例Bean完全初始化之后才能执行初始化逻辑的场景。这通常涉及一些较为复杂的初始化任务,比如依赖于多个服务的集成或状态检查。下面是一个使用SmartInitializingSingleton的示例:

xxl-job源码中初始化执行器有这么一段

public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationContextAware, SmartInitializingSingleton, DisposableBean {private static final Logger logger = LoggerFactory.getLogger(XxlJobSpringExecutor.class);// start@Overridepublic void afterSingletonsInstantiated() {// init JobHandler Repository/*initJobHandlerRepository(applicationContext);*/// init JobHandler Repository (for method)initJobHandlerMethodRepository(applicationContext);// refresh GlueFactoryGlueFactory.refreshInstance(1);// super starttry {super.start();} catch (Exception e) {throw new RuntimeException(e);}}省略.......
}

调用了父类得start()方法

干了几件事

/ 初始化日志路径
XxlJobFileAppender.initLogPath(logPath);// 创建调度器的客户端
initAdminBizList(adminAddresses, accessToken);// 初始化日志清理线程
JobLogFileCleanThread.getInstance().start(logRetentionDays);// 初始化Trigger回调线程
TriggerCallbackThread.getInstance().start();// 初始化执行器服务器
initEmbedServer(address, ip, port, appname, accessToken);

这两个示例展示了CommandLineRunnerSmartInitializingSingleton的不同使用场景,前者适合简单的、不需要依赖其他Bean完全初始化的任务,后者适合较为复杂的、需要确保所有依赖都已经就绪的任务。

版权声明:

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

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