最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot工程啟動(dòng)時(shí)自動(dòng)執(zhí)行任務(wù)實(shí)現(xiàn)方式

 更新時(shí)間:2025年09月04日 10:08:36   作者:angushine  
在SpringBoot中,推薦通過(guò)ApplicationRunner/CommandLineRunner或ApplicationReadyEvent監(jiān)聽(tīng)實(shí)現(xiàn)啟動(dòng)時(shí)自動(dòng)執(zhí)行MQ任務(wù),確保應(yīng)用完全就緒,避免依賴未初始化問(wèn)題,同時(shí)需配置連接池、重試機(jī)制及多環(huán)境控制,保障系統(tǒng)穩(wěn)定與資源優(yōu)雅關(guān)閉

在 Spring Boot 中實(shí)現(xiàn)工程啟動(dòng)時(shí)自動(dòng)執(zhí)行任務(wù)(如開(kāi)始消費(fèi) MQ 數(shù)據(jù))有多種可靠的方式。

以下是幾種常用的方法:

1.使用CommandLineRunner或ApplicationRunner接口

2.使用@PostConstruct注解

3.使用ApplicationListener監(jiān)聽(tīng)ApplicationReadyEvent事件

4.使用@EventListener注解監(jiān)聽(tīng)?wèi)?yīng)用上下文事件

其中,推薦使用ApplicationRunner或CommandLineRunner,或者監(jiān)聽(tīng)ApplicationReadyEvent事件,因?yàn)榇藭r(shí)應(yīng)用上下文已經(jīng)完全準(zhǔn)備好,避免在應(yīng)用還未完全初始化時(shí)就執(zhí)行任務(wù)。

推薦實(shí)現(xiàn)方案

  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;
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 應(yīng)用啟動(dòng)后立即執(zhí)行
        mqConsumerService.startConsuming();
    }
}

特點(diǎn)??:

  • 在 ApplicationContext完全加載后執(zhí)行
  • 可以訪問(wèn)所有 Spring Bean
  • 支持多個(gè) Runner 并指定執(zhí)行順序
  1. 使用 @EventListener監(jiān)聽(tīng) 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() {
        // 應(yīng)用完全啟動(dòng)后執(zhí)行
        mqConsumerService.startConsuming();
    }
}

特點(diǎn)??:

  • 在應(yīng)用完全就緒后執(zhí)行(包括所有 Runner 執(zhí)行完畢)
  • 確保所有 Bean 已初始化完成
  • 避免在上下文未完全準(zhǔn)備好時(shí)操作
  1. 使用 SmartLifecycle接口(適合長(zhǎng)期運(yùn)行任務(wù))
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;
    }

    @Override
    public void start() {
        if (!running) {
            mqConsumerService.startConsuming();
            running = true;
        }
    }

    @Override
    public void stop() {
        if (running) {
            mqConsumerService.stopConsuming();
            running = false;
        }
    }

    @Override
    public boolean isRunning() {
        return running;
    }

    @Override
    public int getPhase() {
        return Integer.MAX_VALUE; // 最后啟動(dòng)
    }
}

特點(diǎn)??:

  • 支持啟動(dòng)/停止生命周期管理
  • 可以控制啟動(dòng)順序(通過(guò) getPhase())
  • 適合需要優(yōu)雅關(guān)閉的資源

MQ 消費(fèi)實(shí)現(xiàn)示例(RabbitMQ)

  1. 配置 RabbitMQ 監(jiān)聽(tīng)器
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. 啟動(dòng)時(shí)自動(dòng)創(chuàng)建隊(duì)列和綁定
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMqConfig {

    @Bean
    public Queue myQueue() {
        return new Queue("${mq.queue.name}", true); // 持久化隊(duì)列
    }
}
  1. 手動(dòng)控制消費(fèi)啟停
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 消費(fèi)實(shí)現(xiàn)示例

  1. 配置 Kafka 監(jiān)聽(tīng)器
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. 手動(dòng)控制消費(fèi)啟停
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();
            }
        });
    }
}

最佳實(shí)踐與注意事項(xiàng)

  1. 啟動(dòng)順序控制
// 使用 @Order 控制多個(gè) Runner 的執(zhí)行順序
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class FirstRunner implements ApplicationRunner {
    // ...
}

@Component
@Order(Ordered.LOWEST_PRECEDENCE)
public class LastRunner implements ApplicationRunner {
    // ...
}
  1. 錯(cuò)誤處理與重試機(jī)制
@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. 優(yōu)雅關(guān)閉
import javax.annotation.PreDestroy;

@Component
public class MqConsumerLifecycle {

    @PreDestroy
    public void onShutdown() {
        // 應(yīng)用關(guān)閉時(shí)停止消費(fèi)
        mqConsumerService.stopConsuming();
    }
}

常見(jiàn)問(wèn)題解決方案

  1. 依賴未初始化問(wèn)題
// 使用 @DependsOn 確保依賴順序
@Component
@DependsOn("mqConnectionFactory")
public class MqConsumerStarter implements ApplicationRunner {
    // ...
}
  1. 配置加載問(wèn)題
@EventListener(ApplicationReadyEvent.class)
public void onApplicationReady() {
    // 確保所有配置已加載
}
  1. 多環(huán)境控制
@Profile("!test") // 不在測(cè)試環(huán)境啟用
@Component
public class ProductionMqConsumer implements ApplicationRunner {
    // ...
}
  1. 并發(fā)啟動(dòng)問(wèn)題
@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) {
    // 單線程順序執(zhí)行
}

總結(jié)

在 Spring Boot 中實(shí)現(xiàn)啟動(dòng)時(shí)自動(dòng)執(zhí)行任務(wù)的最佳實(shí)踐:

1.?? 推薦使用??:

  • ApplicationRunner或 CommandLineRunner:簡(jiǎn)單直接
  • @EventListener(ApplicationReadyEvent.class):確保完全就緒

2.?? 復(fù)雜場(chǎng)景??:

  • SmartLifecycle:需要生命周期管理
  • @PostConstruct+ @Async:異步執(zhí)行

3.?? 關(guān)鍵注意事項(xiàng)??:

  • 確保依賴已初始化
  • 添加錯(cuò)誤處理和重試機(jī)制
  • 實(shí)現(xiàn)優(yōu)雅關(guān)閉
  • 集成健康檢查
  • 多環(huán)境配置控制

4.?? MQ 消費(fèi)最佳實(shí)踐??:

  • 使用 Spring 原生支持(如 @RabbitListener)
  • 配置連接池和重試機(jī)制
  • 監(jiān)控消費(fèi)狀態(tài)和性能

通過(guò)以上方法,可以可靠的在 Spring Boot 應(yīng)用啟動(dòng)時(shí)自動(dòng)執(zhí)行 MQ 消費(fèi)等初始化任務(wù),確保系統(tǒng)穩(wěn)定運(yùn)行。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java21在spring boot中使用虛擬線程的方法

    Java21在spring boot中使用虛擬線程的方法

    本文給大家介紹Java21在spring boot中使用虛擬線程的方法,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2025-08-08
  • 詳解Spring boot Admin 使用eureka監(jiān)控服務(wù)

    詳解Spring boot Admin 使用eureka監(jiān)控服務(wù)

    本篇文章主要介紹了詳解Spring boot Admin 使用eureka監(jiān)控服務(wù),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • Spring?AOP中的環(huán)繞通知詳解

    Spring?AOP中的環(huán)繞通知詳解

    AOP是一種思想,是對(duì)某一類事情的集中處理,接下來(lái)我們要學(xué)習(xí)的是運(yùn)用了AOP思想,進(jìn)行AOP的環(huán)繞處理,本文通過(guò)實(shí)例講解Spring?AOP中的環(huán)繞通知,感興趣的朋友一起看看吧
    2024-07-07
  • 2020最新版idea激活教程(推薦)

    2020最新版idea激活教程(推薦)

    這篇文章主要介紹了2020最新版idea激活教程,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02
  • SpringBoot 緩存源碼分析

    SpringBoot 緩存源碼分析

    JSR107是Java規(guī)范請(qǐng)求,定義了緩存接口,如CachingProvider、CacheManager、Cache等,SpringCache是Spring對(duì)緩存的抽象,通過(guò)@EnableCaching開(kāi)啟緩存注解,使用@Cacheable、@CachePut、@CacheEvict等注解進(jìn)行緩存操作,本文介紹SpringBoot 緩存的相關(guān)知識(shí),感興趣的朋友一起看看
    2025-12-12
  • SpringBoot集成Mybatis并測(cè)試

    SpringBoot集成Mybatis并測(cè)試

    這篇文章主要介紹了SpringBoot集成Mybatis并測(cè)試,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02
  • Struts2源碼分析之ParametersInterceptor攔截器

    Struts2源碼分析之ParametersInterceptor攔截器

    這篇文章主要介紹了Struts2源碼分析之ParametersInterceptor攔截器,ParametersInterceptor攔截器其主要功能是把ActionContext中的請(qǐng)求參數(shù)設(shè)置到ValueStack中,,需要的朋友可以參考下
    2019-06-06
  • 基于JVM 調(diào)優(yōu)的技巧總結(jié)分析

    基于JVM 調(diào)優(yōu)的技巧總結(jié)分析

    本篇文章是對(duì)JVM 調(diào)優(yōu)的技巧進(jìn)行了總結(jié)和分析。需要的朋友參考下
    2013-05-05
  • spring security實(shí)現(xiàn)下次自動(dòng)登錄功能過(guò)程解析

    spring security實(shí)現(xiàn)下次自動(dòng)登錄功能過(guò)程解析

    這篇文章主要介紹了spring security實(shí)現(xiàn)記住我下次自動(dòng)登錄功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • 一文秒懂Java enum常見(jiàn)的用法講解

    一文秒懂Java enum常見(jiàn)的用法講解

    這篇文章主要介紹了一文秒懂Java enum常見(jiàn)的用法講解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12

最新評(píng)論

莲花县| 云安县| 神农架林区| 前郭尔| 堆龙德庆县| 吉木乃县| 平罗县| 吉安市| 若尔盖县| 武功县| 禹州市| 通江县| 页游| 汕头市| 丹东市| 当阳市| 凭祥市| 出国| 加查县| 宁武县| 碌曲县| 周至县| 靖宇县| 神木县| 调兵山市| 苗栗县| 巴楚县| 新和县| 稷山县| 龙江县| 瓦房店市| 东安县| 万源市| 凤凰县| 徐闻县| 阳曲县| 威远县| 西宁市| 五家渠市| 益阳市| 昌黎县|