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

Springboot異步事件配置和使用示例詳解

 更新時(shí)間:2024年10月24日 08:59:34   作者:冰雪女媧  
Spring框架提供了一套事件處理機(jī)制,允許應(yīng)用在各個(gè)組件之間傳遞狀態(tài)信息,自定義事件通常繼承自ApplicationEvent類,Springboot通過自動配置簡化了異步處理的配置,實(shí)現(xiàn)開箱即用,Spring事件模型核心是觀察者模式,適用于解耦和提高響應(yīng)速度

Spring中提供了完整的事件處理機(jī)制,本身底層內(nèi)置實(shí)現(xiàn)了一些事件和監(jiān)聽,同時(shí)支持開發(fā)者擴(kuò)展自己的事件和監(jiān)聽實(shí)現(xiàn)。

一般這種基于事件的實(shí)現(xiàn)在項(xiàng)目實(shí)際開發(fā)中我們主要用來解耦,和做異步處理(默認(rèn)是同步),提供應(yīng)用的響應(yīng)速度。

核心架構(gòu)

先簡要看一下,在Spring中要實(shí)現(xiàn)自定義事件監(jiān)聽需要涉及哪些接口類,這里忽略異步的引用、注解的實(shí)現(xiàn),后面會說到。

image

基本實(shí)現(xiàn)步驟

  • 自定義事件:一般繼承自ApplicationEvent即可,注意里面要去定義和實(shí)現(xiàn)自己的事件方法,也就是具體這個(gè)事件要做什么事,一般就在事件類、或者基于事件類去實(shí)現(xiàn)即可。
  • 事件發(fā)布:業(yè)務(wù)代碼中注入ApplicationEventPublisher類,然后再具體業(yè)務(wù)方法中調(diào)用publishEvent方法,傳入上面自定義的事件,以及自定義的必要參數(shù)等信息
  • 實(shí)現(xiàn)事件監(jiān)聽:有了事件、也發(fā)布了,那必須有對應(yīng)的監(jiān)聽來調(diào)用具體的事件,一般實(shí)現(xiàn)ApplicationListener泛型傳入自己的事件類型即可

注意事項(xiàng)

  • 異常和事物:默認(rèn)情況下事件的發(fā)布、監(jiān)聽處理都是和當(dāng)前業(yè)務(wù)線程綁定到一起的,也就是在同一個(gè)線程中操作事件任務(wù)。因此無論是事件發(fā)布時(shí)導(dǎo)致異常,或者是具體事件任務(wù)實(shí)現(xiàn)的方法異常,都會導(dǎo)致當(dāng)前業(yè)務(wù)異常;相應(yīng)的如果當(dāng)前業(yè)務(wù)有事物,那么異常了也會回滾。
  • 事件類型:首先一定要自定義自己的事件,其次在監(jiān)聽的時(shí)候也是監(jiān)聽自己的事件,而不是監(jiān)聽基類或者接口然后去判斷,這樣反而失去了基于事件監(jiān)聽編程靈活性,同時(shí)也違法開閉原則,并不利于后期擴(kuò)展。具體事件中可以定義其他一些額外的參數(shù),這樣方便在具體方法中傳參使用
  • 事件順序:一次可以發(fā)布多個(gè)事件,無論是同一個(gè)還是不同的,執(zhí)行順序默認(rèn)也是按照發(fā)布順序。

場景應(yīng)用

這里以訂單完成和推送給平臺訂單相關(guān)數(shù)據(jù)為業(yè)務(wù)模型來舉例說明。Spring4.2之后提供了注解來實(shí)現(xiàn)事件監(jiān)聽,非常的方便,這里我們使用注解的方式實(shí)現(xiàn)監(jiān)聽即可。

  • 縮略的業(yè)務(wù)類:包含事件的發(fā)布
@Resource
private ApplicationEventPublisher publisher;
public void completeTrade(TradeOrder trade){
  tradeMapper.modifyStatus(trade);
  publisher.publishEvent(new TradeStatusEvent(this,new TradeStatusEvent.Params(trade,"完成訂單")));
}
  • 具體事件的定義:繼承自ApplicationEvent
public class TradeStatusEvent extends ApplicationEvent {
    private static final Logger logger = LoggerFactory.getLogger(TradeStatusEvent.class);
    private Params params;
    public Params getParams(){
      return this.params;
    }
    public TradeStatusEvent(Object source,Params param) {
        super(source);
        this.param = param;
    }
    public void send(){
      try{
        HttpUtils.send("xx.oo", PlatformBean.Builder().note(this.params.note)..build());
      } catch(Exception e){
        logger.error("TradeStatusEvent處理異常:",e);
      } 
    }
    public static class Params {
        private TradeOrder trade;
        private String note;
        //get、set 定義其他參數(shù)等
    }
}
  • 監(jiān)聽實(shí)現(xiàn):使用注解,注意這里我使用了 事務(wù)監(jiān)聽注解 ,按照具體業(yè)務(wù)場景可以選擇具體的注解,比如最常用的@EventListener。因?yàn)槲疫@里的訴求是當(dāng)前事物提交完成之后再去推送消息,而且實(shí)際情況是啟用了異步監(jiān)聽來實(shí)現(xiàn),同時(shí)有的人在監(jiān)聽的方法中可能還執(zhí)行了回查,也就是去查詢業(yè)務(wù)中提交的數(shù)據(jù),那如果這里不標(biāo)記為事物提交之后執(zhí)行,在異步情況下無法獲取到數(shù)據(jù)
@Component
public class TradeStatusEventListener {
    @TransactionalEventListener(phase= TransactionPhase.AFTER_COMMIT, fallbackExecution=true)
    void handlerAfterComplete(TradeStatusEvent event) {
        event.send();
    }
}

異步實(shí)現(xiàn)

所謂異步實(shí)現(xiàn),一般是指異步監(jiān)聽,將主體業(yè)務(wù)邏輯和消息監(jiān)聽任務(wù)放到不同的線程去執(zhí)行,提高業(yè)務(wù)的響應(yīng)速度。

Springboot中我們有多個(gè)辦法來實(shí)現(xiàn)異步監(jiān)聽執(zhí)行,最簡單、最直接的就和異步方法實(shí)現(xiàn)一模一樣,只需在監(jiān)聽方法上加上@Async注解(前提是啟用了異步執(zhí)行)

  • 第一種辦法:Configuration配置類中加上注解@EnableAsync,啟用Spring的異步方法執(zhí)行能力。然后在監(jiān)聽方法上加上@Async注解,標(biāo)明此方法是異步執(zhí)行。Over就這樣就行了【我們沒有配置異步線程對不對?那是會直接new Thread()來執(zhí)行異步任務(wù)嗎,當(dāng)然不是,而是Spring默認(rèn)提供并初始化了一個(gè)專門用來執(zhí)行異步任務(wù)的線程池ThreadPoolTaskExecutor,會接管所有的異步任務(wù)在同一個(gè)線程池中執(zhí)行。也支持定制化處理,后續(xù)我們會說到】
@Configuration
@EnableAsync
public class AppConfig{}
//````
@Component
public class TradeStatusEventListener {
    @Async
    @TransactionalEventListener(phase= TransactionPhase.AFTER_COMMIT, fallbackExecution=true)
    void handlerAfterComplete(TradeStatusEvent event) {
        event.send();
    }
}
  • 第二種辦法:如果說不想全局開啟異步,只是想給事件監(jiān)聽的代碼實(shí)現(xiàn)異步任務(wù)呢?那最簡單就是直接在監(jiān)聽哪里new Thread().start(),不受控、不優(yōu)雅,但是業(yè)務(wù)場景簡單,訪問量小的情況下也不是不可以。那要規(guī)范一點(diǎn)呢,就是自己創(chuàng)建一個(gè)線程池,比如ExecutorService executorService = Executors.newCachedThreadPool();然后在event.send哪里使用executorService.execute(..)執(zhí)行即可。
  • 第三種辦法:優(yōu)雅點(diǎn)實(shí)現(xiàn),創(chuàng)建SimpleApplicationEventMulticaster的Bean,然后創(chuàng)建一個(gè)線程池給塞進(jìn)去,注意需要把自定義實(shí)現(xiàn)注入到Spring容器中。其他代碼不用做任何修改,就像同步邏輯一樣,在事件發(fā)布的時(shí)候廣播會使用multicastEvent調(diào)用taskExecutor獲取一個(gè)線程去執(zhí)行監(jiān)聽任務(wù)
@Configuration
public class AppConfig{
  @Bean
  public SimpleApplicationEventMulticaster simpleApplicationEventMulticaster(){
        SimpleApplicationEventMulticaster mu = new SimpleApplicationEventMulticaster();
        //這里我使用spring提供的任務(wù)構(gòu)造器創(chuàng)建了一個(gè)立即執(zhí)行的有界隊(duì)列任務(wù)線程池
        Executor taskExecutor = new TaskExecutorBuilder().corePoolSize(8).maxPoolSize(200).queueCapacity(20).threadNamePrefix("trade-send-").build();
        mu.setTaskExecutor(taskExecutor);
        //設(shè)置異常處理
        mu.setErrorHandler((t)->{
            //logger.error("==========調(diào)用平臺發(fā)送消息方法失敗,",t);
        });
    return mu;
  }
}

框架原理

  • 為什么異步監(jiān)聽只需要@EnableAsync、以及在方法上加上@Async就可以了呢?

當(dāng)我們使用Springboot,引入starter時(shí)會自動引入spring-boot-autoconfigure,此包里面實(shí)現(xiàn)了很多自動配置的功能(約定大于配置)名字都是xxxAutoConfiguration,比如我們這里要說的就是TaskExecutionAutoConfiguration,容器啟動的時(shí)候就會加載和創(chuàng)建默認(rèn)的任務(wù)線程池,可以通過spring.task.execution開頭屬性來配置。需要注意的是,無論是否加入@EnableAsync注解TaskExecutionAutoConfiguration都會初始化一個(gè)默認(rèn)的線程池,因?yàn)檫@個(gè)是全局的。

image

@EnableAsync的作用是在容器啟動的時(shí)候,告訴Spring我可要支持異步處理任務(wù)了,你看著辦。Spring所好的朋友,我給你準(zhǔn)備了一個(gè)專門搞事的攔截器。

image

  • 當(dāng)我們加入了注解,Spring會將按照配置將準(zhǔn)備工作全部做完,從而做到開箱即用,直接一步到位。

總結(jié)

  • Spring事件模型的四個(gè)核心:事件源也就是業(yè)務(wù)方、事件、廣播器、監(jiān)聽器
  • 事件機(jī)制支持同步、異步,按需調(diào)整和使用。使用異步監(jiān)聽時(shí),推薦使用線程池管理線程,高效、穩(wěn)定而且易于維護(hù)。
  • 使用Springboot時(shí)通過注解的方式監(jiān)聽、啟用異步盡享絲滑。實(shí)際原理核心就是觀察者模式。

到此這篇關(guān)于Springboot異步事件配置和使用的文章就介紹到這了,更多相關(guān)Springboot異步事件配置內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于mybatis-plus 時(shí)間字段比較

    基于mybatis-plus 時(shí)間字段比較

    這篇文章主要介紹了mybatis-plus 時(shí)間字段的比較,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • SpringMVC框架如何與Junit整合看這個(gè)就夠了

    SpringMVC框架如何與Junit整合看這個(gè)就夠了

    這篇文章主要介紹了SpringMVC框架如何與Junit整合看這個(gè)就夠了,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • java交換排序之奇偶排序?qū)崿F(xiàn)方法

    java交換排序之奇偶排序?qū)崿F(xiàn)方法

    這篇文章主要介紹了java交換排序之奇偶排序?qū)崿F(xiàn)方法,實(shí)例分析了奇偶排序的原理與具體實(shí)現(xiàn)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-02-02
  • Java并發(fā)工具之CyclicBarrier使用詳解

    Java并發(fā)工具之CyclicBarrier使用詳解

    這篇文章主要介紹了Java并發(fā)工具之CyclicBarrier使用詳解,CyclicBarrier是一個(gè)同步器,允許一組線程相互之間等待,直到到達(dá)某個(gè)公共屏障點(diǎn)(common barrier point),再繼續(xù)執(zhí)行,需要的朋友可以參考下
    2023-12-12
  • Java 異常處理小結(jié),從入門到精通

    Java 異常處理小結(jié),從入門到精通

    這篇文章主要介紹了Java 異常處理小結(jié),從入門到精通,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • java中的常見排序示例代碼(含優(yōu)化方案和拓展方法)

    java中的常見排序示例代碼(含優(yōu)化方案和拓展方法)

    在Java中常見的排序算法包括冒泡排序、選擇排序、插入排序、希爾排序、歸并排序、快速排序和堆排序等,這篇文章主要介紹了java中常見排序(含優(yōu)化方案和拓展方法)的相關(guān)資料,需要的朋友可以參考下
    2026-01-01
  • 淺談java中OO的概念和設(shè)計(jì)原則(必看)

    淺談java中OO的概念和設(shè)計(jì)原則(必看)

    下面小編就為大家?guī)硪黄獪\談java中OO的概念和設(shè)計(jì)原則(必看)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05
  • Java8新特性之默認(rèn)方法和靜態(tài)方法

    Java8新特性之默認(rèn)方法和靜態(tài)方法

    這篇文章主要給大家介紹了關(guān)于Java8新特性之默認(rèn)方法和靜態(tài)方法的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • java實(shí)現(xiàn)中綴表達(dá)式轉(zhuǎn)后綴的方法

    java實(shí)現(xiàn)中綴表達(dá)式轉(zhuǎn)后綴的方法

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)中綴表達(dá)式轉(zhuǎn)后綴的表達(dá)式方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • Java事務(wù)的個(gè)人理解小結(jié)

    Java事務(wù)的個(gè)人理解小結(jié)

    數(shù)據(jù)庫操作的事務(wù)習(xí)慣上就稱為Java事務(wù)
    2013-03-03

最新評論

虎林市| 内乡县| 舞钢市| 襄垣县| 扎兰屯市| 资中县| 汉川市| 南丰县| 长武县| 焉耆| 延寿县| 临汾市| 安顺市| 太和县| 朝阳区| 循化| 金川县| 西吉县| 砀山县| 固始县| 井研县| 昌乐县| 博罗县| 贵港市| 德保县| 天台县| 萨嘎县| 南岸区| 连江县| 焦作市| 长白| 林州市| 阿拉尔市| 如东县| 双桥区| 高陵县| 明光市| 芜湖县| 西宁市| 于田县| 罗平县|