当前位置:首页 > 科技  > 软件

京东一面:如何在SpringBoot启动时执行特定代码?

来源: 责编: 时间:2024-04-07 17:04:46 286观看
导读引言Spring Boot 提供了许多便捷的功能和特性,使得开发者可以更加轻松地构建强大、高效的应用程序。然而,在应用程序启动时执行一些初始化操作是至关重要的,它可以确保应用程序在启动后处于预期的状态,从而提供更好的用户

引言

Spring Boot 提供了许多便捷的功能和特性,使得开发者可以更加轻松地构建强大、高效的应用程序。然而,在应用程序启动时执行一些初始化操作是至关重要的,它可以确保应用程序在启动后处于预期的状态,从而提供更好的用户体验和稳定性。J9V28资讯网——每日最新资讯28at.com

在应用程序启动时执行初始化操作有许多好处。首先,它可以确保应用程序在启动后的初始状态是正确的,避免了在应用程序运行时出现意外情况。其次,它可以在应用程序准备好接受请求之前完成一些必要的设置,例如加载配置、建立数据库连接、缓存预热等。总的来说,执行初始化操作可以确保应用程序以正确的方式启动,并为后续操作提供一个稳定的基础。J9V28资讯网——每日最新资讯28at.com

图片图片J9V28资讯网——每日最新资讯28at.com

监听 ApplicationContext事件

Spring Boot应用程序启动时执行初始化操作的方法是通过监听ApplicationContext事件。ContextRefreshedEvent事件表示ApplicationContext被初始化或刷新时触发的事件。通过监听这个事件,开发者可以在应用程序启动后执行一些必要的初始化操作。J9V28资讯网——每日最新资讯28at.com

图片图片J9V28资讯网——每日最新资讯28at.com

示例:J9V28资讯网——每日最新资讯28at.com

@Componentpublic class MyContextRefreshedListener implements ApplicationListener<ContextRefreshedEvent> {    @Override    public void onApplicationEvent(ContextRefreshedEvent event) {        System.out.println("监听到ContextRefreshedEvent事件,开始初始化操作。。。。。。。");    }}

这种方式适合以下场景:J9V28资讯网——每日最新资讯28at.com

  1. 1. 执行一次性初始化操作: 当应用程序启动时,可能需要执行一些只需在应用程序初始化阶段执行一次的操作,例如加载基础数据、建立连接等。通过监听 ContextRefreshedEvent 事件,可以确保这些初始化操作在应用程序启动后立即执行。
  2. 2. 初始化缓存或缓存刷新: 如果应用程序使用了缓存,可能需要在应用程序启动时初始化缓存或定期刷新缓存。通过监听 ContextRefreshedEvent 事件,可以在应用程序启动后立即执行缓存初始化或刷新操作,确保缓存数据是最新的。
  3. 3. 执行与外部系统的交互: 在应用程序启动时,可能需要与外部系统进行交互,例如检查外部系统的可用性、加载配置信息等。通过监听 ContextRefreshedEvent 事件,可以在应用程序启动后立即执行与外部系统的交互操作,确保应用程序在启动后处于正常工作状态。
  4. 4. 执行与 Spring Bean 相关的初始化操作: 在应用程序启动时,可能需要执行一些与 Spring Bean 相关的初始化操作,例如在数据库连接池初始化后执行数据库迁移、在消息队列连接初始化后执行订阅操作等。通过监听 ContextRefreshedEvent 事件,可以确保这些初始化操作在 Spring Bean 初始化完成后立即执行

这种方式能够确保在 ApplicationContext 被完全初始化或刷新后执行初始化操作,可以在这个时机执行一些需要ApplicationContext完全准备好的操作。但是需要注意的是,ContextRefreshedEvent 事件可能会在应用程序的刷新周期内多次触发,因此在处理这个事件时需要谨慎处理,避免重复执行初始化逻辑。J9V28资讯网——每日最新资讯28at.com

实现CommandLineRunner接口

CommandLineRunner是Spring Boot提供的一个接口,它有一个run方法,当Spring Boot应用上下文初始化完成后,会自动查找并执行所有实现了CommandLineRunner接口的Bean的run方法。CommandLineRunner接口实际上是Spring Boot对Spring框架生命周期管理的一个扩展,通过对接口的实现,我们可以在Spring Boot应用启动后的特定阶段执行自定义的初始化逻辑。J9V28资讯网——每日最新资讯28at.com

图片图片J9V28资讯网——每日最新资讯28at.com

示例:J9V28资讯网——每日最新资讯28at.com

@Componentpublic class MyCommandLineRunner implements CommandLineRunner {    @Override    public void run(String... args) throws Exception {        System.out.println("MyCommandLineRunner.run()方法执行了");    }}

使用场景:J9V28资讯网——每日最新资讯28at.com

  1. 1. 命令行参数处理:CommandLineRunner接口常用于处理从命令行传入的参数,例如运行不同模式下的任务(如dev模式、prod模式)、读取配置项等。
  2. 2. 应用启动后的一次性操作:在应用启动后,可能需要进行一些一次性执行的任务,如数据库表结构检查、初始化缓存、发送通知邮件等。

使用CommandLineRunner接口这种方式是,我们只需要实现接口,无需关注容器的生命周期事件或手动注册监听器。但是如果是多个CommandLineRunner之间的执行顺序无法保证,可能会带来不确定性(如果是不关心顺序,那就不是缺点了)。另外,我们不应该在`` run方法中实现过多或较为复杂的任务。J9V28资讯网——每日最新资讯28at.com

实现ApplicationRunner接口

ApplicationRunner是Spring Boot提供的另一个接口,它也有一个run方法,与CommandLineRunner接口非常相似。当Spring Boot应用启动并且ApplicationContext初始化完成后,Spring Boot会查找并执行所有实现了ApplicationRunner接口的Bean的run方法。J9V28资讯网——每日最新资讯28at.com

图片图片J9V28资讯网——每日最新资讯28at.com

ApplicationRunner的主要特点是其run方法接收一个ApplicationArguments参数,它可以更好地解析和处理命令行参数,包括选项参数(键值对)和非选项参数。J9V28资讯网——每日最新资讯28at.com

示例:J9V28资讯网——每日最新资讯28at.com

@Componentpublic class ApplicationArgumentProcessor implements ApplicationRunner {    @Override    public void run(ApplicationArguments args) throws Exception {        System.out.println("ApplicationArgumentProcessor.run()方法执行了");    }}

使用场景:J9V28资讯网——每日最新资讯28at.com

  • 命令行参数解析:由于ApplicationArguments提供了丰富的参数解析能力,因此更适合处理带有键值对形式的命令行参数,如--server-port=8080,然后根据这些参数执行不同的初始化操作。
@Componentpublic class ApplicationArgumentProcessor implements ApplicationRunner {    @Override    public void run(ApplicationArguments args) throws Exception {        Optional<Integer> port = args.getOptionValues("server-port").stream()                .map(Integer::parseInt)                .findFirst();        if (port.isPresent()) {            // 根据端口号进行特定的初始化操作        }    }}
  • 启动时初始化:同CommandLineRunner,也可用于执行启动后的一次性操作,例如读取配置、初始化缓存、检查系统资源等,同时可以根据解析的命令行参数决定初始化的具体内容。

相比较于CommandLineRunner,ApplicationRunner提供了更强大的命令行参数解析功能,可以轻松处理各种类型的参数。可以根据命令行参数灵活调整启动时的初始化逻辑。但是其缺点同CommandLineRunner。J9V28资讯网——每日最新资讯28at.com

ApplicationRunner和CommandLineRunner都可以用来在Spring Boot启动时执行特定代码,两者在应用场景上略有差异,具体选择哪种取决于项目的实际需求和命令行参数的复杂程度。J9V28资讯网——每日最新资讯28at.com

使用@PostConstruct注解

@PostConstruct注解是JSR-250规范的一部分,Spring框架对此提供了支持。当Spring容器管理的Bean完成依赖注入后,会自动调用标注有@PostConstruct的方法。这个注解应用于无参或void返回值的方法上,表明该方法应在依赖注入完成后,但在Bean实例正式投入使用之前调用。J9V28资讯网——每日最新资讯28at.com

在Spring Boot启动时,当Spring容器初始化并创建Bean时,如果发现某个Bean上有@PostConstruct注解的方法,则会在Bean的生命周期的初始化阶段调用这个方法。J9V28资讯网——每日最新资讯28at.com

@Servicepublic class UserService {    @Autowired    private UserRepository userRepository;        @PostConstruct    public void init() {        // 在依赖注入完成后,执行初始化操作        System.out.println("UserService初始化...");        // 初始化数据库连接、缓存或者其他内部状态    }}

使用场景:J9V28资讯网——每日最新资讯28at.com

1. 单个Bean初始化:对于某个特定的Bean,在其所有依赖项注入完成后,需要执行一些特定的初始化操作,例如数据库连接初始化、缓存预热、初始化内部状态等。J9V28资讯网——每日最新资讯28at.com

2. 资源初始化:对于一些公共资源,如线程池、数据库连接池等,可以在对应的配置类或服务类中使用@PostConstruct来完成初始化设置。J9V28资讯网——每日最新资讯28at.com

@PostConstruct注解只需要在需要执行初始化操作的方法上加上即可,无需额外实现接口或关注Spring容器的生命周期事件。并且针对性强,仅针对单个Bean进行初始化操作,有助于提高代码的模块化和复用性。J9V28资讯网——每日最新资讯28at.com

但是如果有多个具有@PostConstruct注解的方法,它们之间没有明确的执行顺序,除非通过Bean间的依赖关系隐式确定顺序。并且针对单个Bean进行初始化操作,所以他并不适合做全局性初始化操作。J9V28资讯网——每日最新资讯28at.com

@Bean注解中指定初始化方法

@Bean注解在Spring框架中用于定义一个Bean的实例化逻辑,通常在配置类中使用。通过在@Bean注解中指定initMethod属性,可以设置一个在Bean实例化并完成依赖注入后执行的方法。当Spring容器创建并注入完所有依赖关系后,会自动调用该Bean上指定的初始化方法。J9V28资讯网——每日最新资讯28at.com

@Configurationpublic class PrePostConfig {    /**     * 指定初始化init     * @return     */    @Bean(initMethod = "init")    BeanWayService beanWayService(){        return new BeanWayService();    }}public class BeanWayService {    public void init() {        System.out.println("@Bean-init-method");    }        public BeanWayService(){        super();        System.out.println("初始化构造函数-BeanWayService");    }}

适用场景:J9V28资讯网——每日最新资讯28at.com

1. 资源初始化:例如,初始化数据库连接、网络连接、线程池等资源。J9V28资讯网——每日最新资讯28at.com

2. Bean状态设置:在Bean实例化后,对其进行额外的状态设定或配置。J9V28资讯网——每日最新资讯28at.com

3. 缓存预热:在服务启动时预先加载部分数据至缓存中。J9V28资讯网——每日最新资讯28at.com

Bean实例上定义初始化方法,与Bean紧密关联,可以精确地控制Bean在何时执行初始化操作,与Spring容器的生命周期绑定,尤其适用于那些需要在Bean实例化后立即执行的操作。。但是如果多个Bean都有初始化方法,它们之间的执行顺序难以控制,除非依赖于Spring容器中Bean的依赖注入顺序。J9V28资讯网——每日最新资讯28at.com

实现InitializingBean接口

InitializingBean是Spring框架中的一个接口,它包含一个方法afterPropertiesSet()。当Spring容器完成了对一个Bean的所有必要属性的依赖注入后,如果该Bean实现了InitializingBean接口,Spring会自动调用其afterPropertiesSet()方法。J9V28资讯网——每日最新资讯28at.com

@Componentpublic class MyService implements InitializingBean {    @Autowired    private Dependency dependency;    @Override    public void afterPropertiesSet() throws Exception {        // 在所有依赖注入完成后执行的初始化逻辑        System.out.println("MyService初始化...");        // 初始化资源、设置状态或执行其他操作    }    // 其他业务方法...}

适用场景:J9V28资讯网——每日最新资讯28at.com

1. 资源初始化:如初始化数据库连接、网络连接、线程池等资源。J9V28资讯网——每日最新资讯28at.com

2. Bean状态设置:在依赖注入完成后,设置Bean的初始状态或执行特定的配置操作。J9V28资讯网——每日最新资讯28at.com

afterPropertiesSet()方法会在所有属性注入完成后执行,确保Bean在使用前完成初始化。不需要额外的注解,只需实现接口就可以定义初始化逻辑。但是其要求Bean实现特定接口,增加了类的耦合度,同时也不符合Spring倡导的基于注解的编程风格。并且需要显式抛出异常。J9V28资讯网——每日最新资讯28at.com

相比较于@PostConstruct,@PostConstruct注解更具语义化且不强制类实现接口,降低了耦合度。推荐优先考虑使用@PostConstruct注解进行初始化逻辑的编写。J9V28资讯网——每日最新资讯28at.com

@EventListener注解

@EventListener 注解在Spring应用程序中定义事件监听器。通过监听 ApplicationReadyEvent事件,我们可以确保在应用程序完全启动并准备好接受请求时执行初始化逻辑。通过在监听器方法上添加 @EventListener 注解,并指定要监听的事件类型,可以在事件发生时执行相应的初始化操作。J9V28资讯网——每日最新资讯28at.com

@Componentpublic class StartupEventListener {    @EventListener(ApplicationReadyEvent.class)    public void onApplicationReadyEvent(ApplicationReadyEvent event) {        System.out.println("Spring Boot应用已启动并准备就绪,开始执行初始化操作...");        // 在这里执行需要在应用启动后进行的初始化代码    }}

适用场景:J9V28资讯网——每日最新资讯28at.com

1. 应用启动后执行一次性操作:如数据初始化、缓存预热、统计信息收集等。J9V28资讯网——每日最新资讯28at.com

2. 等待所有Bean初始化后再执行:当需要确保所有Bean都已经初始化完毕再执行某些操作时。J9V28资讯网——每日最新资讯28at.com

通过事件驱动的方式,将初始化逻辑与Bean的创建逻辑解耦开来,并且可以监听多种事件类型(例如:ContextRefreshedEvent),不仅仅是应用启动事件,还可用于其他业务场景。相比于@PostConstruct、CommandLineRunner或ApplicationRunner等机制,@EventListener监听的ApplicationReadyEvent在Spring Boot启动流程中的执行时机较晚,所有Bean都已经初始化并准备就绪后才会触发。J9V28资讯网——每日最新资讯28at.com

总结

本文全面探讨了Spring Boot启动阶段执行初始化操作的几种常见方法,包括监听事件、实现接口以及使用注解等多种策略,具体如下:J9V28资讯网——每日最新资讯28at.com

1. 监听ApplicationContext事件:通过实现ApplicationListener<ContextRefreshedEvent>接口,监听ContextRefreshedEvent事件,可在Spring容器初始化完成后执行初始化逻辑。这种方式适用于需要在所有Bean加载完毕后进行全局性初始化操作的场景。J9V28资讯网——每日最新资讯28at.com

2. 实现CommandLineRunner接口:Spring Boot启动后,会自动调用实现了CommandLineRunner接口的Bean的run方法,该方法可以处理命令行参数并执行启动时的特定操作。适用于需要根据命令行参数执行初始化逻辑或进行启动后一次性任务的情况。J9V28资讯网——每日最新资讯28at.com

3. 实现ApplicationRunner接口:与CommandLineRunner类似,ApplicationRunner也在Spring Boot启动后执行其run方法,但其参数为ApplicationArguments,提供了更强大的命令行参数解析功能。适合处理键值对形式的命令行参数并据此执行初始化任务。J9V28资讯网——每日最新资讯28at.com

4. 使用@PostConstruct注解:在Bean的方法上添加@PostConstruct注解,Spring会在该Bean的所有依赖注入完成后调用该方法进行初始化。这种方法用于单个Bean初始化完成后的特定逻辑,增强了代码的模块化和可维护性。J9V28资讯网——每日最新资讯28at.com

5. @Bean注解中指定初始化方法:通过@Bean注解中的initMethod属性指定Bean的初始化方法,该方法在Bean实例化并完成注入后由Spring容器调用。这种方法适用于需要对特定Bean进行精细化初始化管理的场景。J9V28资讯网——每日最新资讯28at.com

6. 实现InitializingBean接口:Bean实现InitializingBean接口并重写afterPropertiesSet方法,也能实现在依赖注入完成后执行初始化逻辑。虽然传统但不如使用@PostConstruct注解优雅,且增加了类的耦合度。J9V28资讯网——每日最新资讯28at.com

7. 使用@EventListener注解:通过监听ApplicationReadyEvent等事件,可以在Spring Boot应用启动并准备就绪后执行初始化任务。这种方式延迟执行,适用于在所有Bean初始化完毕且应用已经完全启动后才需要进行的操作。J9V28资讯网——每日最新资讯28at.com

每种方法均有其适用场景和优缺点,我们应根据项目需求和具体情况选择最适合的初始化方式。通过熟练掌握和灵活运用这些方法,能够有效地管理和优化Spring Boot应用的启动流程,确保应用程序在启动之初即进入正常运作状态。J9V28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-81730-0.html京东一面:如何在SpringBoot启动时执行特定代码?

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 动态支付策略:Go 语言中策略模式的妙用,你学会了吗?

下一篇: 一篇文章告诉你真实场景下服务端接口性能问题是如何解决的

标签:
  • 热门焦点
  • 轿车从天而降电动车主被撞身亡 超速抢道所致:现场视频让网友吵翻

    近日,上海青浦区法院判决轿车从天而降电动车主被撞身亡案,轿车车主被判有期徒刑一年。案件显示当时男子驾驶轿车在上海某路段行驶,前车忽然转弯提速超车,
  • 线程通讯的三种方法!通俗易懂

    线程通信是指多个线程之间通过某种机制进行协调和交互,例如,线程等待和通知机制就是线程通讯的主要手段之一。 在 Java 中,线程等待和通知的实现手段有以下几种方式:Object 类下
  • 量化指标是与非:挽救被量化指标扼杀的技术团队

    作者 | 刘新翠整理 | 徐杰承本文整理自快狗打车技术总监刘新翠在WOT2023大会上的主题分享,更多精彩内容及现场PPT,请关注51CTO技术栈公众号,发消息【WOT2023PPT】即可直接领取
  • 十个简单但很有用的Python装饰器

    装饰器(Decorators)是Python中一种强大而灵活的功能,用于修改或增强函数或类的行为。装饰器本质上是一个函数,它接受另一个函数或类作为参数,并返回一个新的函数或类。它们通常用
  • 为什么你不应该使用Div作为可点击元素

    按钮是为任何网络应用程序提供交互性的最常见方式。但我们经常倾向于使用其他HTML元素,如 div span 等作为 clickable 元素。但通过这样做,我们错过了许多内置浏览器的功能。
  • 零售大模型“干中学”,攀爬数字化珠峰

    文/侯煜编辑/cc来源/华尔街科技眼对于绝大多数登山爱好者而言,攀爬珠穆朗玛峰可谓终极目标。攀登珠峰的商业路线有两条,一是尼泊尔境内的南坡路线,一是中国境内的北坡路线。相
  • 重估百度丨“晚熟”的百度云,能等到春天吗?

    &copy;自象限原创作者|程心排版|王喻可2016年7月13日,百度云计算战略发布会在北京举行,宣告着百度智能云的正式启程。彼时的会场座无虚席,甚至排队排到了门外,在场的所有人几乎都
  • 破圈是B站头上的紧箍咒

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之每年的暑期档都少不了瞄准追剧女孩们的古偶剧集,2021年有优酷的《山河令》,2022年有爱奇艺的《苍兰诀》,今年却轮到小破站抓住了追
  • 猿辅导与新东方的两种“归途”

    作者|卓心月 出品|零态LT(ID:LingTai_LT)如何成为一家伟大企业?答案一定是对&ldquo;势&rdquo;的把握,这其中最关键的当属对企业战略的制定,且能够站在未来看现在,即使这其中的
Top