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

springboot?publish?event?事件機(jī)制demo分享

 更新時(shí)間:2022年10月27日 09:40:08   作者:阿拉的夢(mèng)想  
這篇文章主要介紹了springboot?publish?event?事件機(jī)制demo,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

1. 使用ApplicationEventPublisher 發(fā)布事件

復(fù)制下面全部代碼,右鍵包名,粘貼即可生成java類(lèi),執(zhí)行即可看到效果。

事件機(jī)制

  • 需要自定義一個(gè)事件類(lèi)繼承ApplicationEvent;
  • 需要自定義一個(gè)監(jiān)聽(tīng)器類(lèi)實(shí)現(xiàn)ApplicationListener接口,或普通類(lèi)的方法中使用@EventListener注解;
  • 使用默認(rèn)發(fā)布器ApplicationEventPublisher發(fā)布即可;
  • 事件類(lèi)不需要注入到IOC;監(jiān)聽(tīng)器需要注入到IOC;ApplicationEventPublisher用Autowired注入進(jìn)來(lái)即可;
  • 默認(rèn)情況下,事件發(fā)布與執(zhí)行是同步的,事件執(zhí)行完畢,發(fā)布者才會(huì)執(zhí)行下面的邏輯;
package com.example.controller;

import com.alibaba.fastjson.JSON;
import com.example.SpringbootRedisApplication;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.Objects;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = SpringbootRedisApplication.class)
@Slf4j
@EnableAsync
public class PublishEventDemo {
    /**
     * 事件機(jī)制:
     * 需要自定義一個(gè)事件類(lèi)繼承ApplicationEvent;
     * 需要自定義一個(gè)監(jiān)聽(tīng)器類(lèi)實(shí)現(xiàn)ApplicationListener接口,或普通類(lèi)的方法中使用@EventListener注解;
     * 使用默認(rèn)發(fā)布器ApplicationEventPublisher發(fā)布即可;
     * 事件類(lèi)不需要注入到IOC;監(jiān)聽(tīng)器需要注入到IOC;ApplicationEventPublisher用Autowired注入進(jìn)來(lái)即可;
     */


    /**
     * 事件發(fā)布器
     */
    @Autowired
    private ApplicationEventPublisher eventPublisher;

    /**
     * 測(cè)試類(lèi)
     */
    @Test
    public void publishTest() throws InterruptedException {
        Task task = new Task();
        task.setId(1L);
        task.setTaskName("測(cè)試任務(wù)");
        task.setTaskContext("任務(wù)內(nèi)容");
        task.setFinish(false);
        MyEvent event = new MyEvent(task);
        log.info("開(kāi)始發(fā)布任務(wù)");
        eventPublisher.publishEvent(event);
        //applicationContext.publishEvent(event);
        log.info("結(jié)束發(fā)布任務(wù)");
        Thread.sleep(10000);
    }
}

/**
 * 任務(wù)類(lèi)
 * 任務(wù)就是一個(gè)普通的類(lèi),用來(lái)保存你要發(fā)布事件的內(nèi)容。這個(gè)沒(méi)有特殊限制,可以根據(jù)自己業(yè)務(wù)隨意設(shè)置。
 */
@Data
class Task {

    private Long id;

    private String taskName;

    private String taskContext;

    private boolean finish;
}

/**
 * 事件類(lèi)
 * 事件類(lèi)需要繼承org.springframework.context.ApplicationEvent,這樣發(fā)布的事件才能被Spring所識(shí)別
 */
@Slf4j
class MyEvent<T> extends ApplicationEvent {

    private Task task;

    public MyEvent(Task task) {
        super(task);
        this.task = task;
    }

    public Task getTask() {
        return task;
    }
}

/**
 * 事件監(jiān)聽(tīng)類(lèi)
 * 事件的監(jiān)聽(tīng)器需要實(shí)現(xiàn)org.springframework.context.ApplicationListener,并且需要注入到容器之中。
 */
@Component
@Slf4j
class MyEventListenerA implements ApplicationListener<MyEvent> {
    /**
     * 監(jiān)聽(tīng)方式1:實(shí)現(xiàn)ApplicationListener接口,重寫(xiě)onApplicationEvent方法
     * 需要使用Component注入IOC
     */
    @SneakyThrows
    @Async
    @Override
    public void onApplicationEvent(MyEvent MyEvent) {
        Thread.sleep(5000);
        if (Objects.isNull(MyEvent)) {
            return;
        }
        Task task = MyEvent.getTask();
        log.info("監(jiān)聽(tīng)器A接收任務(wù):{}", JSON.toJSONString(task));
        task.setFinish(true);
        log.info("監(jiān)聽(tīng)器A此時(shí)完成任務(wù)");

    }
}

@Component
@Slf4j
class MyEventListenerB implements ApplicationListener<MyEvent> {
    /**
     * 監(jiān)聽(tīng)方式2:接口和注解混合使用
     * 但此時(shí) @EventListener不能與注解@Async在同一個(gè)類(lèi)中使用,會(huì)報(bào)錯(cuò),至于為什么,不知道;
     * 需要使用Component注入IOC
     */
    //@Async//加上這個(gè),@EventListener的方法就會(huì)報(bào)java.lang.IllegalStateException: Failed to load ApplicationContext
    @SneakyThrows
    @Override
    public void onApplicationEvent(MyEvent MyEvent) {
        Thread.sleep(1000);
        if (Objects.isNull(MyEvent)) {
            return;
        }
        Task task = MyEvent.getTask();
        log.info("監(jiān)聽(tīng)器B接收任務(wù):{}", JSON.toJSONString(task));
        task.setFinish(true);
        log.info("監(jiān)聽(tīng)器B此時(shí)完成任務(wù)");
    }

    @EventListener
    public void someMethod(MyEvent event) throws InterruptedException {
        Thread.sleep(1000);
        log.info("監(jiān)聽(tīng)器@EventListenerB收到={}", event.getTask());
    }
}


@Component
@Slf4j
class MyEventListennerC {
    /**
     * 監(jiān)聽(tīng)方式3:注解@EventListener的監(jiān)聽(tīng)器不需要實(shí)現(xiàn)任何接口
     * 需要使用Component注入IOC
     */
    @EventListener
    public void someMethod(MyEvent event) throws InterruptedException {
        Thread.sleep(1000);
        log.info("監(jiān)聽(tīng)器@EventListenerC收到={}", event.getTask());
    }
}

運(yùn)行日志:

2020-11-30 18:13:56.238  INFO 19776 --- [           main] com.example.controller.PublishEventDemo  : Started PublishEventDemo in 11.098 seconds (JVM running for 13.737)
2020-11-30 18:13:56.902  INFO 19776 --- [           main] com.example.controller.PublishEventDemo  : 開(kāi)始發(fā)布任務(wù)
2020-11-30 18:13:57.904  INFO 19776 --- [           main] com.example.controller.MyEventListenerB  : 監(jiān)聽(tīng)器@EventListenerB收到=Task(id=1, taskName=測(cè)試任務(wù), taskContext=任務(wù)內(nèi)容, finish=false)
2020-11-30 18:13:58.905  INFO 19776 --- [           main] c.example.controller.MyEventListennerC   : 監(jiān)聽(tīng)器@EventListenerC收到=Task(id=1, taskName=測(cè)試任務(wù), taskContext=任務(wù)內(nèi)容, finish=false)
2020-11-30 18:13:59.920  INFO 19776 --- [           main] com.example.controller.MyEventListenerB  : 監(jiān)聽(tīng)器B接收任務(wù):{"finish":false,"id":1,"taskContext":"任務(wù)內(nèi)容","taskName":"測(cè)試任務(wù)"}
2020-11-30 18:13:59.921  INFO 19776 --- [           main] com.example.controller.MyEventListenerB  : 監(jiān)聽(tīng)器B此時(shí)完成任務(wù)
2020-11-30 18:13:59.921  INFO 19776 --- [           main] com.example.controller.PublishEventDemo  : 結(jié)束發(fā)布任務(wù)
2020-11-30 18:14:03.913  INFO 19776 --- [         task-1] com.example.controller.MyEventListenerA  : 監(jiān)聽(tīng)器A接收任務(wù):{"finish":true,"id":1,"taskContext":"任務(wù)內(nèi)容","taskName":"測(cè)試任務(wù)"}
2020-11-30 18:14:03.913  INFO 19776 --- [         task-1] com.example.controller.MyEventListenerA  : 監(jiān)聽(tīng)器A此時(shí)完成任務(wù)
2020-11-30 18:14:09.958  INFO 19776 --- [       Thread-3] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'

事件發(fā)送后,會(huì)等待事件執(zhí)行完畢,因此他們是同步的。若想異步執(zhí)行事件,可以把@Async加到監(jiān)聽(tīng)方法上;

2. 使用ApplicationContext發(fā)布事件

與上例不同之處

  • 使用ApplicationContext發(fā)布事件,ApplicationContext實(shí)現(xiàn)了ApplicationEventPublisher接口;
  • 使用ApplicationContextEvent 定義事件,ApplicationContextEvent 繼承了ApplicationEvent類(lèi);

demo代碼:

package com.example.controller;

import ch.qos.logback.classic.Logger;
import com.example.SpringbootRedisApplication;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ApplicationContextEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.bind.annotation.RestController;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = SpringbootRedisApplication.class)
@RestController
@Slf4j
public class PublishEventDemo2 {
    /**
     * 使用ApplicationContext發(fā)布事件
     */
    @Autowired
    ApplicationContext applicationContext;

    @Test
    public void send() {
        MyEvent2 myEvent2 = new MyEvent2(applicationContext);
        myEvent2.setData("數(shù)據(jù)");
        log.info("開(kāi)始發(fā)送事件");
        applicationContext.publishEvent(myEvent2);
        log.info("結(jié)束發(fā)送事件");
    }
}

/**
 * 監(jiān)聽(tīng)器類(lèi)
 */
@Slf4j
@Component
class MyEventListener2 implements ApplicationListener<MyEvent2> {
    @Override
    public void onApplicationEvent(MyEvent2 event) {
        log.info("監(jiān)聽(tīng)器MyEventListener2收到={}", event);
    }

    @EventListener
    public void someMethod(MyEvent2 event) {
        log.info("監(jiān)聽(tīng)器MyEventListener2@EventListener收到={}", event);
    }
}

/**
 * 監(jiān)聽(tīng)器類(lèi)
 */
@Slf4j
@Component
class MyEventListenner1 {
    @EventListener
    public void someMethod(MyEvent2 event) {
        log.info("監(jiān)聽(tīng)器MyEventListenner1收到={}", event);
    }
}

/**
 * 事件類(lèi)
 *
 * @param <T>
 */
@ToString
class MyEvent2<T> extends ApplicationContextEvent {
    private T data;

    public MyEvent2(ApplicationContext source) {
        super(source);
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

運(yùn)行日志:

2020-11-30 18:03:38.638  INFO 15792 --- [           main] c.example.controller.PublishEventDemo2   : Started PublishEventDemo2 in 9.571 seconds (JVM running for 12.677)
2020-11-30 18:03:39.355  INFO 15792 --- [           main] c.example.controller.PublishEventDemo2   : 開(kāi)始發(fā)送事件
2020-11-30 18:03:39.358  INFO 15792 --- [           main] com.example.controller.MyEventListener2  : 監(jiān)聽(tīng)器MyEventListener2@EventListener收到=MyEvent2(data=數(shù)據(jù))
2020-11-30 18:03:39.359  INFO 15792 --- [           main] c.example.controller.MyEventListenner1   : 監(jiān)聽(tīng)器MyEventListenner1收到=MyEvent2(data=數(shù)據(jù))
2020-11-30 18:03:39.359  INFO 15792 --- [           main] com.example.controller.MyEventListener2  : 監(jiān)聽(tīng)器MyEventListener2收到=MyEvent2(data=數(shù)據(jù))
2020-11-30 18:03:39.359  INFO 15792 --- [           main] c.example.controller.PublishEventDemo2   : 結(jié)束發(fā)送事件
2020-11-30 18:03:39.435  INFO 15792 --- [       Thread-3] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'

事件發(fā)送后,會(huì)等待事件執(zhí)行完畢,因此他們是同步的。若想異步執(zhí)行事件,可以把@Async加到監(jiān)聽(tīng)方法上;

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

相關(guān)文章

  • 快速搭建Spring Boot+MyBatis的項(xiàng)目IDEA(附源碼下載)

    快速搭建Spring Boot+MyBatis的項(xiàng)目IDEA(附源碼下載)

    這篇文章主要介紹了快速搭建Spring Boot+MyBatis的項(xiàng)目IDEA(附源碼下載),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Java算法之計(jì)數(shù)排序、桶排序、基數(shù)排序?qū)崿F(xiàn)代碼

    Java算法之計(jì)數(shù)排序、桶排序、基數(shù)排序?qū)崿F(xiàn)代碼

    這篇文章主要介紹了Java算法之計(jì)數(shù)排序、桶排序、基數(shù)排序?qū)崿F(xiàn)的相關(guān)資料,分別通過(guò)計(jì)數(shù)、分桶和位數(shù)處理實(shí)現(xiàn)高效穩(wěn)定排序,文中通過(guò)代碼及圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2025-05-05
  • Spring Cloud之注冊(cè)中心Nacos的使用詳解

    Spring Cloud之注冊(cè)中心Nacos的使用詳解

    本文介紹SpringCloud Alibaba中的Nacos組件,對(duì)比了Nacos與Eureka的區(qū)別,展示了如何在項(xiàng)目中引入SpringCloud Alibaba和Nacos,并配置負(fù)載均衡,通過(guò)實(shí)際操作,驗(yàn)證了服務(wù)注冊(cè)和負(fù)載均衡的功能,感興趣的朋友一起看看吧
    2025-03-03
  • 阿里通用OCR文字識(shí)別/圖像識(shí)別/圖片識(shí)別對(duì)接代碼示例(Java篇)

    阿里通用OCR文字識(shí)別/圖像識(shí)別/圖片識(shí)別對(duì)接代碼示例(Java篇)

    這篇文章主要介紹了阿里通用OCR文字識(shí)別/圖像識(shí)別/圖片識(shí)別對(duì)接(Java篇)的相關(guān)資料,文中詳細(xì)介紹了包括開(kāi)通服務(wù)、測(cè)試圖片、編寫(xiě)識(shí)別代碼、處理識(shí)別結(jié)果等步驟,需要的朋友可以參考下
    2024-12-12
  • mybatisplus駝峰命名映射的問(wèn)題解決

    mybatisplus駝峰命名映射的問(wèn)題解決

    本文主要介紹了mybatisplus駝峰命名映射的問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • TKMybatis的介紹和使用詳解

    TKMybatis的介紹和使用詳解

    TKMybatis 是基于 Mybatis 框架開(kāi)發(fā)的一個(gè)工具,本文主要介紹了TKMybatis的介紹和使用詳解,內(nèi)部實(shí)現(xiàn)了對(duì)單表的基本數(shù)據(jù)操作,只需要簡(jiǎn)單繼承 TKMybatis 提供的接口,就能夠?qū)崿F(xiàn)無(wú)需編寫(xiě)任何 sql 即能完成單表操作,感興趣的可以了解一下
    2021-12-12
  • Spring事務(wù)處理Transactional,鎖同步和并發(fā)線程

    Spring事務(wù)處理Transactional,鎖同步和并發(fā)線程

    本文詳細(xì)講解了Spring事務(wù)處理Transactional,鎖同步和并發(fā)線程。對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • Lombok不生效,提示java:?找不到符號(hào)的解決方案

    Lombok不生效,提示java:?找不到符號(hào)的解決方案

    這篇文章主要介紹了Lombok不生效,提示java:?找不到符號(hào)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • jpa使用uuid策略后無(wú)法手動(dòng)設(shè)置id的問(wèn)題及解決

    jpa使用uuid策略后無(wú)法手動(dòng)設(shè)置id的問(wèn)題及解決

    這篇文章主要介紹了jpa使用uuid策略后無(wú)法手動(dòng)設(shè)置id的問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • java 實(shí)現(xiàn)定時(shí)的方法及實(shí)例代碼

    java 實(shí)現(xiàn)定時(shí)的方法及實(shí)例代碼

    這篇文章主要介紹了java 定時(shí)任務(wù)詳細(xì)介紹及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-03-03

最新評(píng)論

荃湾区| 花莲市| 仙桃市| 凤凰县| 曲麻莱县| 安达市| 遂溪县| 雷州市| 晋宁县| 比如县| 岑溪市| 西华县| 土默特左旗| 永登县| 龙胜| 陇西县| 固安县| 万州区| 贺州市| 白朗县| 苍山县| 扶余县| 九寨沟县| 阿瓦提县| 尤溪县| 股票| 威宁| 博野县| 巴彦淖尔市| 滨海县| 保靖县| 克什克腾旗| 洛阳市| 盘山县| 墨脱县| 九台市| 沙洋县| 宜良县| 永昌县| 木兰县| 河东区|