当前位置: 首页 > news >正文

Spring Boot 工程启动时自动执行任务方法

在 Spring Boot 中实现工程启动时自动执行任务(如开始消费 MQ 数据)有多种可靠的方式。以下是几种常用的方法:
1.使用CommandLineRunner或ApplicationRunner接口
2.使用@PostConstruct注解
3.使用ApplicationListener监听ApplicationReadyEvent事件
4.使用@EventListener注解监听应用上下文事件
其中,推荐使用ApplicationRunner或CommandLineRunner,或者监听ApplicationReadyEvent事件,因为此时应用上下文已经完全准备好,避免在应用还未完全初始化时就执行任务。

推荐实现方案

  1. 使用 ApplicationRunner或 CommandLineRunner(最常用)
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;@Component
public class MqConsumerStarter implements ApplicationRunner {private final MqConsumerService mqConsumerService;public MqConsumerStarter(MqConsumerService mqConsumerService) {this.mqConsumerService = mqConsumerService;}@Overridepublic void run(ApplicationArguments args) throws Exception {// 应用启动后立即执行mqConsumerService.startConsuming();}
}

特点​​:
• 在 ApplicationContext完全加载后执行
• 可以访问所有 Spring Bean
• 支持多个 Runner 并指定执行顺序

  1. 使用 @EventListener监听 ApplicationReadyEvent
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;@Component
public class MqConsumerInitializer {private final MqConsumerService mqConsumerService;public MqConsumerInitializer(MqConsumerService mqConsumerService) {this.mqConsumerService = mqConsumerService;}@EventListener(ApplicationReadyEvent.class)public void onApplicationReady() {// 应用完全启动后执行mqConsumerService.startConsuming();}
}

特点​​:
• 在应用完全就绪后执行(包括所有 Runner 执行完毕)
• 确保所有 Bean 已初始化完成
• 避免在上下文未完全准备好时操作

  1. 使用 SmartLifecycle接口(适合长期运行任务)
import org.springframework.context.SmartLifecycle;
import org.springframework.stereotype.Component;@Component
public class MqConsumerLifecycle implements SmartLifecycle {private final MqConsumerService mqConsumerService;private volatile boolean running = false;public MqConsumerLifecycle(MqConsumerService mqConsumerService) {this.mqConsumerService = mqConsumerService;}@Overridepublic void start() {if (!running) {mqConsumerService.startConsuming();running = true;}}@Overridepublic void stop() {if (running) {mqConsumerService.stopConsuming();running = false;}}@Overridepublic boolean isRunning() {return running;}@Overridepublic int getPhase() {return Integer.MAX_VALUE; // 最后启动}
}

特点​​:
• 支持启动/停止生命周期管理
• 可以控制启动顺序(通过 getPhase())
• 适合需要优雅关闭的资源

MQ 消费实现示例(RabbitMQ)

  1. 配置 RabbitMQ 监听器
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;@Component
public class RabbitMqConsumer {@RabbitListener(queues = "${mq.queue.name}")public void handleMessage(String message) {System.out.println("Received message: " + message);// 处理消息逻辑}
}
  1. 启动时自动创建队列和绑定
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RabbitMqConfig {@Beanpublic Queue myQueue() {return new Queue("${mq.queue.name}", true); // 持久化队列}
}
  1. 手动控制消费启停
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.stereotype.Service;@Service
public class MqConsumerService {private final SimpleMessageListenerContainer container;public MqConsumerService(SimpleMessageListenerContainer container) {this.container = container;}public void startConsuming() {if (!container.isRunning()) {container.start();}}public void stopConsuming() {if (container.isRunning()) {container.stop();}}
}

Kafka 消费实现示例

  1. 配置 Kafka 监听器
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;@Component
public class KafkaConsumer {@KafkaListener(topics = "${kafka.topic.name}", groupId = "${kafka.group.id}")public void listen(String message) {System.out.println("Received Message: " + message);// 处理消息逻辑}
}
  1. 手动控制消费启停
import org.springframework.kafka.config.KafkaListenerEndpointRegistry;
import org.springframework.stereotype.Service;@Service
public class KafkaConsumerService {private final KafkaListenerEndpointRegistry registry;public KafkaConsumerService(KafkaListenerEndpointRegistry registry) {this.registry = registry;}public void startConsuming() {registry.getListenerContainers().forEach(container -> {if (!container.isRunning()) {container.start();}});}public void stopConsuming() {registry.getListenerContainers().forEach(container -> {if (container.isRunning()) {container.stop();}});}
}

最佳实践与注意事项

  1. 启动顺序控制
// 使用 @Order 控制多个 Runner 的执行顺序
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class FirstRunner implements ApplicationRunner {// ...
}@Component
@Order(Ordered.LOWEST_PRECEDENCE)
public class LastRunner implements ApplicationRunner {// ...
}
  1. 错误处理与重试机制
@Override
public void run(ApplicationArguments args) {try {mqConsumerService.startConsuming();} catch (Exception e) {// 添加重试逻辑int maxRetries = 5;for (int i = 0; i < maxRetries; i++) {try {Thread.sleep(5000); // 等待5秒重试mqConsumerService.startConsuming();break;} catch (Exception ex) {logger.error("Retry {} failed: {}", i+1, ex.getMessage());}}}
}
  1. 优雅关闭
import javax.annotation.PreDestroy;@Component
public class MqConsumerLifecycle {@PreDestroypublic void onShutdown() {// 应用关闭时停止消费mqConsumerService.stopConsuming();}
}

常见问题解决方案

  1. 依赖未初始化问题
// 使用 @DependsOn 确保依赖顺序
@Component
@DependsOn("mqConnectionFactory")
public class MqConsumerStarter implements ApplicationRunner {// ...
}
  1. 配置加载问题
@EventListener(ApplicationReadyEvent.class)
public void onApplicationReady() {// 确保所有配置已加载
}
  1. 多环境控制
@Profile("!test") // 不在测试环境启用
@Component
public class ProductionMqConsumer implements ApplicationRunner {// ...
}
  1. 并发启动问题
@Bean
public TaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(1);executor.setMaxPoolSize(1);executor.setWaitForTasksToCompleteOnShutdown(true);return executor;
}@Async("taskExecutor")
@Override
public void run(ApplicationArguments args) {// 单线程顺序执行
}

总结

在 Spring Boot 中实现启动时自动执行任务的最佳实践:
1.​​ 推荐使用​​:
• ApplicationRunner或 CommandLineRunner:简单直接
• @EventListener(ApplicationReadyEvent.class):确保完全就绪
2.​​ 复杂场景​​:
• SmartLifecycle:需要生命周期管理
• @PostConstruct+ @Async:异步执行
3.​​ 关键注意事项​​:
• 确保依赖已初始化
• 添加错误处理和重试机制
• 实现优雅关闭
• 集成健康检查
• 多环境配置控制
4.​​ MQ 消费最佳实践​​:
• 使用 Spring 原生支持(如 @RabbitListener)
• 配置连接池和重试机制
• 监控消费状态和性能
通过以上方法,可以可靠的在 Spring Boot 应用启动时自动执行 MQ 消费等初始化任务,确保系统稳定运行。

http://www.dtcms.com/a/364435.html

相关文章:

  • 图像正向扭曲反向扭曲
  • 安全测试漫谈:如何利用X-Forwarded-For头进行IP欺骗与防护
  • 停止所有dcoker容器
  • [UT]记录uvm_config_db的错误:get中的第二个参数设置为this
  • 第6章:垃圾回收分析与调优
  • 【NVIDIA B200】1.alltoall_perf 单机性能深度分析:基于 alltoall_perf 测试数据
  • 从卡顿到丝滑:3 个实战场景教你搞定代码性能优化
  • DeepSeek、GPT-5都在卷的“快慢脑”,腾讯中科院给出了更优解:还是多模态的!
  • 什么是科技成果鉴定测试?成果鉴定测试报告带给企业什么好处?
  • c语言链表:从入门到精通
  • 深度学习篇---SGD+Momentum优化器
  • wpf之Border
  • 嵌入式 - 硬件:51单片机(2)
  • 08、Linux 安全组开放端口
  • sed——Stream Editor流编辑器
  • 软件测试中的Bug知识总结
  • 81-dify案例分享-零代码用 Dify 使用梦 AI 3.0 多模态模型,免费生成影视级视频
  • 光伏设计方案怎么对比?360°展示规避空间问题
  • Bug 排查日记:从入门到精通
  • 微服务多级缓存:从问题到实战(小白也能看懂的亿级流量方案)
  • MP4视频太大如何压缩?分享6种简单便捷的压缩小技巧
  • 微服务的编程测评系统20-虚拟机-nginx-部署
  • dockerfile文件的用途
  • Day20_【机器学习—逻辑回归 (2)—分类评估方法】
  • 机器学习与深度学习的 Python 基础之 NumPy(2)
  • 构建安全的自动驾驶:软件测试中的编码规范与AI验证
  • 数据结构_循环队列_牺牲一个存储空间_不牺牲额外的存储空间 Circular Queue(C语言实现_超详细)
  • 机器学习-逻辑回归
  • 数据结构:图的表示 (Representation of Graphs)
  • 下一代自动驾驶汽车系统XIL验证方法