亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

spring中ApplicationListener的使用小結(jié)

 更新時(shí)間:2024年07月08日 09:21:43   作者:孟秋與你  
ApplicationListener是spring提供的一個(gè)監(jiān)聽(tīng)器,本文主要介紹了spring中ApplicationListener的使用小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

ApplicationListener 是spring提供的一個(gè)監(jiān)聽(tīng)器,它可以實(shí)現(xiàn)一個(gè)簡(jiǎn)單的發(fā)布-訂閱功能,用有點(diǎn)外行但最簡(jiǎn)單通俗的話來(lái)解釋?zhuān)罕O(jiān)聽(tīng)到主業(yè)務(wù)在執(zhí)行到了某個(gè)節(jié)點(diǎn)之后,在監(jiān)聽(tīng)器里面做出相應(yīng)的其它業(yè)務(wù)變更。下面我們具體看段代碼,則能很快的理解

使用示例:

首先定義一個(gè)業(yè)務(wù)實(shí)體類(lèi),實(shí)體類(lèi)定義字段、get set方法、構(gòu)造函數(shù)

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor

/**
 * 模擬業(yè)務(wù)對(duì)象實(shí)體類(lèi)
 * @author csdn:孟秋與你
 */
public class MyBizEntity {
    private String name;
    private Integer age;
}

再定義一個(gè)事件,事件繼承ApplicationEvent

import org.springframework.context.ApplicationEvent;

/**
 * 自定義事件(繼承ApplicationEvent)
 * @author csdn:孟秋與你
 */
public class MyEvent extends ApplicationEvent {


    public MyEvent(Object source) {
        super(source);
    }
    public MyEvent() {
        // java基礎(chǔ):如果父類(lèi)只有有參構(gòu)造 子類(lèi)需要使用其它構(gòu)造函數(shù) 必須在構(gòu)造函數(shù)第一行調(diào)用super 因?yàn)樽宇?lèi)也是調(diào)用父類(lèi)的構(gòu)造函數(shù)
        super(null);
        // do other
    }
}

定義一個(gè)監(jiān)聽(tīng)器,實(shí)現(xiàn)ApplicationListener接口:

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 * 監(jiān)聽(tīng)事件
 */
@Component
public class MyApplicationListener implements ApplicationListener {
    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {

        // 必須判斷自己要的類(lèi)型  因?yàn)闀?huì)監(jiān)聽(tīng)到所有繼承ApplicationEvent的事件
        if (applicationEvent instanceof MyEvent) {
            Object source = applicationEvent.getSource();
            MyBizEntity bizEntity = (MyBizEntity) source;
            System.out.println(bizEntity.getName() + ":------------name");
        }

    }
}


寫(xiě)一個(gè)接口進(jìn)行測(cè)試, 此時(shí)監(jiān)聽(tīng)器就能打印輸出了

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/test/listener")
@RestController
public class MainBizController {

    @Autowired
    private ApplicationContext context;

    @GetMapping
    public String test() {
        // do something
        
        // 模擬要傳遞的業(yè)務(wù)對(duì)象
        MyBizEntity bizEntity = new MyBizEntity("name",18);
        MyEvent event = new MyEvent(bizEntity);
        // 上下文 發(fā)布事件
        context.publishEvent(event);
        return "success";
    }
}


原理簡(jiǎn)析:

為什么發(fā)布了事件,監(jiān)聽(tīng)器就能夠監(jiān)聽(tīng)到呢? 其實(shí)原理很簡(jiǎn)單,就是spring進(jìn)行了一個(gè)樸實(shí)無(wú)華的直接調(diào)用, 我們來(lái)看看源碼:

context.publishEvent默認(rèn)是調(diào)用AbstractApplicationContext類(lèi)的publishEvent方法,而publishEvent方法里面調(diào)用了SimpleApplicationEventMulticaster 類(lèi)的multicastEvent方法。

tips: 為什么上下文有publishEvent方法 ?
因?yàn)锳pplicationContext繼承了ApplicationEventPublisher

在這里插入圖片描述

SimpleApplicationEventMulticaster: 首先會(huì)獲取所有實(shí)現(xiàn)了ApplicationListener的監(jiān)聽(tīng)器 (get by type就可以獲取到), 接著會(huì)執(zhí)行 invokeListener方法

在這里插入圖片描述

我們看看最后doInvokeListener 做了什么:

在這里插入圖片描述

通過(guò)上面源碼鏈路,我們不難發(fā)現(xiàn) 其實(shí)就是調(diào)用了publishEvent方法后,spring在我們不輕易能看到的地方 去調(diào)用了一下監(jiān)聽(tīng)器的onApplicationEvent 方法而已,通過(guò)源碼我們也可以看到 默認(rèn)是同步調(diào)用(沒(méi)有定義taskExecutor時(shí)), 本質(zhì)上是一個(gè)解耦,把原本可能要寫(xiě)在一起的業(yè)務(wù)代碼拆分了。

如何異步發(fā)送

通過(guò)源碼可以看到 SimpleApplicationEventMulticaster類(lèi)的multicastEvent方法,會(huì)先獲取Executor ,如果有executor 則通過(guò)異步方式發(fā)送

所以問(wèn)題就變成了這個(gè)executor如何才能獲取到值。

在這里插入圖片描述

可以看到該類(lèi)有一個(gè)public的setTaskExecutor方法

在這里插入圖片描述

所以我們可以直接將該類(lèi)的實(shí)例作為一個(gè)bean給spring托管,代碼如下

@Configuration
public class EventConfig {

    @Bean(name = "applicationEventMulticaster")
    public SimpleApplicationEventMulticaster simpleApplicationEventMulticaster(TaskExecutor taskExecutor) {
        SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster();
        eventMulticaster.setTaskExecutor(taskExecutor);
        return eventMulticaster;
    }
}

這里涉及到一個(gè)spring的基礎(chǔ)知識(shí),上面代碼的參數(shù)是(TaskExecutor taskExecutor) 所以需要先有一個(gè)executor bean,代碼示例如下:

@Configuration
public class AsyncInBootConfig {

    /** 核心線程池大小 */
    private int corePoolSize = 20;

    /**
     * 最大可創(chuàng)建的線程數(shù)
     */
    private int maxPoolSize = 50;

    /**
     * 隊(duì)列最大長(zhǎng)度
     */
    private int queueCapacity = 100;

    /**
     * 線程池維護(hù)線程所允許的空閑時(shí)間
     */
    private int keepAliveSeconds = 300;

    @Primary
    @Bean(name = "threadPool")
    /**
     * springboot 線程池方式
     */
    public ThreadPoolTaskExecutor threadPoolTaskExecutor()
    {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setMaxPoolSize(maxPoolSize);
        executor.setCorePoolSize(corePoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setKeepAliveSeconds(keepAliveSeconds);
        // 線程池對(duì)拒絕任務(wù)(無(wú)線程可用)的處理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }
}


這樣在發(fā)布消息時(shí),就會(huì)使用全局配置的這個(gè)threadPool線程池了

到此這篇關(guān)于spring中ApplicationListener的使用小結(jié)的文章就介紹到這了,更多相關(guān)spring ApplicationListener內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入了解Java設(shè)計(jì)模式之UML類(lèi)圖

    深入了解Java設(shè)計(jì)模式之UML類(lèi)圖

    UML?即?Unified?Modeling?Language?統(tǒng)一建模語(yǔ)言,是用來(lái)設(shè)計(jì)軟件的可視化建模語(yǔ)言。本文就帶大家了解一下UML中類(lèi)圖的定義與使用,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-11-11
  • Java中List分片的5種方法小結(jié)

    Java中List分片的5種方法小結(jié)

    本文主要介紹了Java中List分片的5種方法小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 如何解決UnsupportedOperationException異常問(wèn)題

    如何解決UnsupportedOperationException異常問(wèn)題

    這篇文章主要介紹了如何解決UnsupportedOperationException異常問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • 深入理解Java中的Properties類(lèi)

    深入理解Java中的Properties類(lèi)

    Properties類(lèi)是Java中用于處理配置文件的工具類(lèi),它繼承自 Hashtable類(lèi),實(shí)現(xiàn)了Map接口,本文主要介紹了Java中的Properties類(lèi),感興趣的可以了解一下
    2024-01-01
  • 基于JavaCore文件的深入分析

    基于JavaCore文件的深入分析

    本篇文章介紹了,對(duì)JavaCore文件的深入分析。需要的朋友參考下
    2013-05-05
  • 官方詳解HDFS?Balancer工具主要調(diào)優(yōu)參數(shù)

    官方詳解HDFS?Balancer工具主要調(diào)優(yōu)參數(shù)

    這篇文章主要為大家介紹了HDFS?Balancer工具主要調(diào)優(yōu)參數(shù)的?官方詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • java開(kāi)源好用的簡(jiǎn)繁轉(zhuǎn)換類(lèi)庫(kù)推薦

    java開(kāi)源好用的簡(jiǎn)繁轉(zhuǎn)換類(lèi)庫(kù)推薦

    這篇文章主要為大家介紹了java開(kāi)源好用的簡(jiǎn)繁轉(zhuǎn)換類(lèi)庫(kù)推薦,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Java一元稀疏多項(xiàng)式計(jì)算器

    Java一元稀疏多項(xiàng)式計(jì)算器

    大家好,本篇文章主要講的是Java一元稀疏多項(xiàng)式計(jì)算器,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • 舉例講解Java的RTTI運(yùn)行時(shí)類(lèi)型識(shí)別機(jī)制

    舉例講解Java的RTTI運(yùn)行時(shí)類(lèi)型識(shí)別機(jī)制

    這篇文章主要介紹了Java的RTTI運(yùn)行時(shí)類(lèi)型識(shí)別機(jī)制,包括泛化的Class引用以及類(lèi)型檢查instanceof等知識(shí)點(diǎn),需要的朋友可以參考下
    2016-05-05
  • springmvc 防止表單重復(fù)提交的兩種方法

    springmvc 防止表單重復(fù)提交的兩種方法

    最近在本地開(kāi)發(fā)測(cè)試的時(shí)候,遇到一個(gè)表單重復(fù)提交的現(xiàn)象。本文主要介紹了springmvc 防止表單重復(fù)提交的兩種方法,感興趣的可以了解一下
    2021-08-08

最新評(píng)論