详解Spring Boot 启动时执行特定代码逻辑的实现方案

书接上回,我们总结了Spring Boot启动过程中都干了些什么,大致分为环境配置、IOC容器bean加载、事件通知等,具体详细总结可自行调转查看。今天我们来看看一个平时在业务开发中常见的逻辑场景。在开发 Spring Boot 应用时,我们经常需要在项目启动时执行一些初始化逻辑,比如加载缓存、连接外部系统、初始化配置信息等。Spring Boot 提供了多种实现方式,允许我们在应用启动的不同阶段插入代码逻辑。本文将结合启动过程详细介绍这些方式,并说明适用的场景及实现示例。


接下来我将一一讲述实现方式,这些操作的源码流程已经在启动过程总结一文中详细叙述过, 这里就只做定义解析和案例展示了,关于源码实现细节可跳转链接查看哈。

1. 使用 CommandLineRunner 和 ApplicationRunner

CommandLineRunnerApplicationRunner 是 Spring Boot 提供的两个接口,用于在应用启动完成后执行逻辑。

  • CommandLineRunner 接收 String[] args 参数,适合处理简单的启动参数。
  • ApplicationRunner 接收 ApplicationArguments 对象,方便解析复杂参数。

CommandLineRunner 示例:

java 复制代码
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
​
@Component
public class MyCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("执行 CommandLineRunner 逻辑!");
        for (String arg : args) {
            System.out.println("启动参数:" + arg);
        }
    }
}

ApplicationRunner 示例:

java 复制代码
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) throws Exception {
        System.out.println("执行 ApplicationRunner 逻辑!");
        if (args.containsOption("debug")) {
            System.out.println("调试模式启动!");
        }
    }
}

适用场景: 在项目启动后立即执行初始化逻辑,例如加载缓存或注册服务。这是笔者比较推荐的方式,用的最多~~~


2. 使用 ApplicationListener 监听启动事件

Spring 提供了丰富的 事件机制 。通过实现 ApplicationListener 接口,我们可以监听应用启动的各个阶段事件,如 ApplicationReadyEvent

示例:

typescript 复制代码
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
​
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationReadyEvent> {
    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        System.out.println("应用启动完成,执行 ApplicationReadyEvent 事件监听逻辑!");
    }
}

适用场景: 当需要在应用完全启动后执行某些操作,如向监控系统注册实例。


3. 使用 @EventListener 注解

@EventListener 注解是一种简化的事件监听机制,允许我们用注解监听特定事件。

java 复制代码
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
​
@Component
public class MyEventListener {
​
    @EventListener(ApplicationStartedEvent.class)
    public void onApplicationStarted() {
        System.out.println("Spring Boot 启动时,执行 ApplicationStartedEvent 监听逻辑!");
    }
}

适用场景: 适用于监听特定事件,如应用启动或关闭时的操作。

上面使用监听事件的两种方式分别监听了事件ApplicationReadyEventApplicationStartedEvent,同类型的事件如下所示,这里就不一一讲述了,感兴趣的可自行写写示例体会下。


项目推荐:基于SpringBoot2.x、SpringCloud和SpringCloudAlibaba企业级系统架构底层框架封装,解决业务开发时常见的非功能性需求,防止重复造轮子,方便业务快速开发和企业技术栈框架统一管理。引入组件化的思想实现高内聚低耦合并且高度可配置化,做到可插拔。严格控制包依赖和统一版本管理,做到最少化依赖。注重代码规范和注释,非常适合个人学习和企业使用

Github地址github.com/plasticene/...

Gitee地址gitee.com/plasticene3...

微信公众号Shepherd进阶笔记

交流探讨qun:Shepherd_126

4. 使用 @PostConstruct 注解

@PostConstruct 注解用于在 Bean 初始化完成后执行逻辑。这是一个标准的 Java 注解,Spring 会在依赖注入完成后调用它标注的方法。

示例:

kotlin 复制代码
​
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
​
@Service
public class MyService {
    @PostConstruct
    public void init() {
        System.out.println("Bean 初始化完成后执行 @PostConstruct 方法!");
    }
}

适用场景: 当需要在某个 Bean 初始化完成后执行逻辑,比如连接数据库、加载外部资源等。


5. 使用 BeanPostProcessor

BeanPostProcessor 接口允许我们在 Bean 初始化前后插入逻辑。

示例:

typescript 复制代码
​
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
​
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
​
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化前处理 Bean:" + beanName);
        return bean;
    }
​
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化后处理 Bean:" + beanName);
        return bean;
    }
}

适用场景: 当需要对某些 Bean 的初始化过程进行增强时。


6. 使用 InitializingBean 接口

InitializingBean 接口中的 afterPropertiesSet() 方法会在 Bean 的属性设置完成后执行。

示例:

java 复制代码
​
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
​
@Component
public class MyInitializingBean implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("Bean 属性设置完成,执行 afterPropertiesSet() 方法!");
    }
}

适用场景: 当需要在 Bean 初始化后执行一些逻辑。


7. 使用 SmartInitializingSingleton 接口

SmartInitializingSingleton 是一个特殊接口,当 所有单例 Bean 初始化完成后 ,会触发 afterSingletonsInstantiated() 方法。

示例:

typescript 复制代码
​
import org.springframework.context.SmartInitializingSingleton;
import org.springframework.stereotype.Component;
​
@Component
public class MySmartInitializingSingleton implements SmartInitializingSingleton {
    @Override
    public void afterSingletonsInstantiated() {
        System.out.println("所有单例 Bean 初始化完成,执行 afterSingletonsInstantiated() 方法!");
    }
}

适用场景: 当需要确保所有单例 Bean 初始化完成后再执行操作。


8. 在 main 方法中执行逻辑

在 Spring Boot 应用的入口方法 main 中,我们也可以执行一些初始化逻辑。

示例:

typescript 复制代码
​
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
​
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        System.out.println("Spring Boot 启动前,执行自定义逻辑!");
        SpringApplication.run(MyApplication.class, args);
        System.out.println("Spring Boot 启动后,执行自定义逻辑!");
    }
}

适用场景: 当需要在应用启动的前后执行全局逻辑时。


总结

实现方式 触发时机 适用场景
CommandLineRunner 应用启动完成后 需要执行启动参数相关逻辑
ApplicationRunner 应用启动完成后 更方便处理复杂启动参数
@PostConstruct Bean 初始化完成后 Bean 的初始化逻辑
ApplicationListener 特定事件触发时 监听应用启动或关闭的事件
@EventListener 特定事件触发时 使用注解简化事件监听
BeanPostProcessor Bean 初始化前后 增强 Bean 的初始化过程
InitializingBean Bean 属性设置完成后 属性注入后的初始化逻辑
SmartInitializingSingleton 所有单例 Bean 初始化完成后 所有 Bean 完成初始化后的逻辑
main方法 应用启动前后 在应用启动前或启动后执行全局逻辑

选择合适的实现方式

  • 需要在应用启动后立即执行逻辑CommandLineRunnerApplicationRunner
  • 需要监听应用的启动事件ApplicationListener@EventListener
  • 需要对 Bean 初始化过程进行控制@PostConstructBeanPostProcessor
  • 需要确保所有 Bean 初始化完成后再执行逻辑SmartInitializingSingleton

不同的实现方式适用于不同的场景,我们可以根据业务需求选择合适的方式,将逻辑插入到 Spring Boot 启动的不同阶段。

相关推荐
麻衣带我去上学26 分钟前
Spring源码学习(五):Spring AOP
java·学习·spring
京东零售技术39 分钟前
加锁失效,非锁之过,加之错也|京东零售供应链库存研发实践
后端
北欧人写代码1 小时前
idea java 项目右键new file时 为什么是 kotlin class 不是普通class
java·kotlin·intellij-idea
笔墨登场说说1 小时前
JDK 里面的线程池和Tomcat线程池的区别
java·servlet·tomcat
on the way 1231 小时前
java.io.IOException: Too many open files
java·开发语言
大鲤余1 小时前
rust 中if let、match -》 options和Result枚举类型
开发语言·后端·rust
m0_571957581 小时前
Java | Leetcode Java题解之第538题把二叉搜索树转换为累加树
java·leetcode·题解
CAORENZHU1 小时前
Java NIO 核心知识.下
java
程序员徐师兄2 小时前
基于 JavaWeb 的宠物商城系统(附源码,文档)
java·vue·springboot·宠物·宠物商城