探秘Spring Boot中的8种初始化操作方式和执行顺序


在 Spring Boot 项目中,初始化操作是不可或缺的一部分。它们确保应用在启动时进行必要的配置、数据加载、资源初始化等工作。本文将深入探讨 Spring Boot 中常见的几种初始化操作方式,并对它们的执行顺序进行比较,帮助你选择最适合你项目的方案。

1. @PostConstruct

@PostConstruct 是 Java 的标准注解,它标记的方法会在依赖注入完成后立即被调用。

import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;

@Component
public class MyPostConstructBean {

    @PostConstruct
    public void init() {
        System.out.println("PostConstruct执行");
    }
}

特点:

  • 适用于简单的初始化逻辑。
  • 依赖注入完成后立即执行。
  • 执行顺序较早。
2. InitializingBean 接口

实现 InitializingBean 接口并重写 afterPropertiesSet 方法,也是进行初始化操作的一种方式。

import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

@Component
public class MyInitializingBean implements InitializingBean {

    @Override
    public void afterPropertiesSet() {
        System.out.println("InitializingBean接口的afterProperiesSet执行");
    }
}

特点:

  • @PostConstruct 更具可读性,适合复杂的初始化逻辑。
  • 依赖注入完成后调用。
  • 执行顺序与 @PostConstruct 类似,但稍晚。
3. @Bean 注解中的 initMethod

使用 @Configuration 配置类中的 @Bean 注解时,可以指定 initMethod 属性来定义初始化方法。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfig {

    @Bean(initMethod = "init")
    public MyBean myBean() {
        return new MyBean();
    }
}

class MyBean {
    public void init() {
        System.out.println("@Bean的initMethod方法执行");
    }
}

特点:

  • 明确指定初始化方法。
  • 更易于配置和管理初始化逻辑。
  • 执行顺序在 @PostConstructInitializingBean 之后。
4. CommandLineRunner 接口

实现 CommandLineRunner 接口的组件会在 Spring Boot 应用启动完成后执行。

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class MyCommandLineRunner implements CommandLineRunner {

    @Override
    public void run(String... args) {
        System.out.println("CommandLineRunner接口的run方法执行");
    }
}

特点:

  • 用于需要在应用完全启动后执行的初始化逻辑。
  • 接受应用启动参数。
  • 执行顺序在所有 Spring 组件初始化完成之后。
5. ApplicationRunner 接口

CommandLineRunner 类似,但提供了更高级的参数解析能力。

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) {
        System.out.println("ApplicationRunner接口的run方法执行");
    }
}

特点:

  • CommandLineRunner 相似,但具有更强的参数处理能力。
  • 用于需要在应用完全启动后执行的初始化逻辑。
  • 执行顺序与 CommandLineRunner 相同。
6. @EventListener事件监听

使用 @EventListener 注解,可以在应用启动的某个生命周期阶段执行初始化逻辑。比如监听 ContextRefreshedEvent 事件,这个事件会在 Spring 上下文初始化或刷新时发布。

import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class MyContextRefreshedListener {

    @EventListener
    public void handleContextRefreshed(ContextRefreshedEvent event) {
        System.out.println("@EventListener监听ContextRefreshedEvent事件执行");
    }
}

特点:

  • 适用于需要在特定生命周期事件发生时执行的初始化逻辑。
  • 可以监听各种生命周期事件,如 ContextRefreshedEventContextClosedEvent 等。
7. SmartInitializingSingleton

实现 SmartInitializingSingleton 接口的 afterSingletonsInstantiated 方法,可以在所有单例 bean 都初始化完成后执行。

import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.stereotype.Component;

@Component
public class MySmartInitializingSingleton implements SmartInitializingSingleton {

    @Override
    public void afterSingletonsInstantiated() {
        System.out.println("SmartInitializingSingleton接口的afterSingletonsInstantiated方法执行");
    }
}

特点:

  • 在所有单例 bean 初始化完成后执行。
  • 适用于需要确保所有单例 bean 都已准备好时执行的初始化逻辑。
8. ApplicationListener

实现 ApplicationListener 接口,可以监听特定的 Spring 事件,如 ApplicationReadyEvent,这个事件在 Spring 应用完全启动后触发。

import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationReadyListener implements ApplicationListener<ApplicationReadyEvent> {

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        System.out.println("监听ApplicationReadyEvent事件,ApplicationListener接口的onApplicationEvent方法执行");
    }
}

特点:

  • 用于在应用完全启动后执行逻辑。
  • 可以监听各种 Spring 事件,提供灵活的初始化时机。
执行顺序综合比较

下面通过代码测试来看看它们的执行顺序,先准备以下代码,通过@Bean创建ExampleBean,在ExampleBean中放入了各种初始化的方式。

@Configuration
public class ExampleConfig {

    @Bean(initMethod = "initMethod")
    public ExampleBean initExampleBean() {
        return new ExampleBean();
    }
}
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import javax.annotation.PostConstruct;


public class ExampleBean implements InitializingBean, CommandLineRunner, ApplicationRunner, SmartInitializingSingleton,
        ApplicationListener<ApplicationReadyEvent> {

    public ExampleBean() {
        System.out.println("构造器执行");
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("InitializingBean接口的afterProperiesSet执行");
    }

    @Override
    public void run(String... args) {
        System.out.println("CommandLineRunner接口的run方法执行");
    }

    @Override
    public void run(ApplicationArguments args) {
        System.out.println("ApplicationRunner接口的run方法执行");
    }

    @Override
    public void afterSingletonsInstantiated() {
        System.out.println("SmartInitializingSingleton接口的afterSingletonsInstantiated方法执行");
    }

    @Override
    public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
        System.out.println("监听ApplicationReadyEvent事件,ApplicationListener接口的onApplicationEvent方法执行");
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("PostConstruct执行");
    }

    public void  initMethod() {
        System.out.println("@Bean标的initMethod方法执行");
    }

    @EventListener
    public void handleContextRefreshed(ContextRefreshedEvent event) {
        System.out.println("@EventListener监听ContextRefreshedEvent事件执行");
    }

}

启动项目运行之后,下面是控制台日志输出结果:

构造器执行
PostConstruct执行
InitializingBean接口的afterProperiesSet执行
@Bean标的initMethod方法执行
SmartInitializingSingleton接口的afterSingletonsInstantiated方法执行
@EventListener监听ContextRefreshedEvent事件执行
...
com.pujiho.practice.MyApplication     : Started LoginApplication in 2.587 seconds (JVM running for 6.749)
...
ApplicationRunner接口的run方法执行
CommandLineRunner接口的run方法执行
监听ApplicationReadyEvent事件,ApplicationListener接口的onApplicationEvent方法执行

所以,综合所有提到的初始化方式,以下是它们的大致执行顺序:

  1. @PostConstruct
  2. InitializingBean.afterPropertiesSet
  3. @BeaninitMethod
  4. SmartInitializingSingleton.afterSingletonsInstantiated
  5. @EventListener (如 ContextRefreshedEvent)
  6. ApplicationRunner.run
  7. CommandLineRunner.run
  8. ApplicationListener (如 ApplicationReadyEvent)
结语

在 Spring Boot 中,选择合适的初始化方式取决于你的具体需求和初始化逻辑的复杂程度。@PostConstructInitializingBean 适合早期的、简单的初始化操作,而 CommandLineRunnerApplicationRunner 更适合在应用完全启动后执行的复杂逻辑。了解这些初始化方式的执行顺序和特点,能够帮助你在项目中做出最佳选择,确保应用的平稳启动。

希望本文能帮助你更好地理解和应用 Spring Boot 中的初始化操作,让你的项目在启动过程中更加高效和可靠。


感谢阅读!如果你对 Spring Boot 还有其他问题或建议,欢迎在评论区交流。

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
《Linux内核探秘:深入解析文件系统和设备驱动的架构与设计》是一本非常有价值的书籍。它深入探索了Linux操作系统内核文件系统和设备驱动的架构和设计。 这本书首先介绍了Linux内核的基本概念和组成部分。它详细描述了Linux文件系统的设计原理和实现方式。文件系统是操作系统用于管理和组织文件的重要组成部分。该书详细介绍了Linux内核常见的文件系统类型,如Ext4、Btrfs和F2FS,并深入探讨了文件系统的数据结构、缓存和访问控制等关键方面。 另外,该书还详细解析了Linux内核的设备驱动程序。设备驱动程序是操作系统与硬件之间的桥梁。这本书介绍了设备驱动程序的基本原理和工作方式,包括设备驱动模型、设备节点和设备文件系统等。同时,书还讨论了设备间通信和驱动程序的编写方法,并提供了实际案例进行说明。 这本书的特点是理论结合实践。书提供了大量的示例代码和实际案例,让读者可以更好地理解和应用所学知识。此外,书还提供了一些常见问题和解决方案,帮助读者更好地解决实际问题。 总之,《Linux内核探秘:深入解析文件系统和设备驱动的架构与设计》是一本对于想要深入了解Linux内核文件系统和设备驱动设计的读者非常有价值的书籍。无论是对于专业人士还是对于Linux爱好者来说,它都是一本不容错过的好书。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值