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

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類,執(zhí)行即可看到效果。

事件機(jī)制

  • 需要自定義一個(gè)事件類繼承ApplicationEvent;
  • 需要自定義一個(gè)監(jiān)聽器類實(shí)現(xiàn)ApplicationListener接口,或普通類的方法中使用@EventListener注解;
  • 使用默認(rèn)發(fā)布器ApplicationEventPublisher發(fā)布即可;
  • 事件類不需要注入到IOC;監(jiān)聽器需要注入到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è)事件類繼承ApplicationEvent;
     * 需要自定義一個(gè)監(jiān)聽器類實(shí)現(xiàn)ApplicationListener接口,或普通類的方法中使用@EventListener注解;
     * 使用默認(rèn)發(fā)布器ApplicationEventPublisher發(fā)布即可;
     * 事件類不需要注入到IOC;監(jiān)聽器需要注入到IOC;ApplicationEventPublisher用Autowired注入進(jìn)來(lái)即可;
     */


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

    /**
     * 測(cè)試類
     */
    @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("開始發(fā)布任務(wù)");
        eventPublisher.publishEvent(event);
        //applicationContext.publishEvent(event);
        log.info("結(jié)束發(fā)布任務(wù)");
        Thread.sleep(10000);
    }
}

/**
 * 任務(wù)類
 * 任務(wù)就是一個(gè)普通的類,用來(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;
}

/**
 * 事件類
 * 事件類需要繼承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)聽類
 * 事件的監(jiān)聽器需要實(shí)現(xiàn)org.springframework.context.ApplicationListener,并且需要注入到容器之中。
 */
@Component
@Slf4j
class MyEventListenerA implements ApplicationListener<MyEvent> {
    /**
     * 監(jiān)聽方式1:實(shí)現(xiàn)ApplicationListener接口,重寫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)聽器A接收任務(wù):{}", JSON.toJSONString(task));
        task.setFinish(true);
        log.info("監(jiān)聽器A此時(shí)完成任務(wù)");

    }
}

@Component
@Slf4j
class MyEventListenerB implements ApplicationListener<MyEvent> {
    /**
     * 監(jiān)聽方式2:接口和注解混合使用
     * 但此時(shí) @EventListener不能與注解@Async在同一個(gè)類中使用,會(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)聽器B接收任務(wù):{}", JSON.toJSONString(task));
        task.setFinish(true);
        log.info("監(jiān)聽器B此時(shí)完成任務(wù)");
    }

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


@Component
@Slf4j
class MyEventListennerC {
    /**
     * 監(jiān)聽方式3:注解@EventListener的監(jiān)聽器不需要實(shí)現(xiàn)任何接口
     * 需要使用Component注入IOC
     */
    @EventListener
    public void someMethod(MyEvent event) throws InterruptedException {
        Thread.sleep(1000);
        log.info("監(jiān)聽器@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  : 開始發(fā)布任務(wù)
2020-11-30 18:13:57.904  INFO 19776 --- [           main] com.example.controller.MyEventListenerB  : 監(jiān)聽器@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)聽器@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)聽器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)聽器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)聽器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)聽器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)聽方法上;

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

與上例不同之處

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

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("開始發(fā)送事件");
        applicationContext.publishEvent(myEvent2);
        log.info("結(jié)束發(fā)送事件");
    }
}

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

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

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

/**
 * 事件類
 *
 * @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   : 開始發(fā)送事件
2020-11-30 18:03:39.358  INFO 15792 --- [           main] com.example.controller.MyEventListener2  : 監(jiān)聽器MyEventListener2@EventListener收到=MyEvent2(data=數(shù)據(jù))
2020-11-30 18:03:39.359  INFO 15792 --- [           main] c.example.controller.MyEventListenner1   : 監(jiān)聽器MyEventListenner1收到=MyEvent2(data=數(shù)據(jù))
2020-11-30 18:03:39.359  INFO 15792 --- [           main] com.example.controller.MyEventListener2  : 監(jiān)聽器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)聽方法上;

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

相關(guān)文章

  • 老生常談Scanner的基本用法

    老生常談Scanner的基本用法

    下面小編就為大家?guī)?lái)一篇老生常談Scanner的基本用法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • IDEA配置靜態(tài)資源熱加載操作(Springboot修改靜態(tài)資源不重啟)

    IDEA配置靜態(tài)資源熱加載操作(Springboot修改靜態(tài)資源不重啟)

    這篇文章主要介紹了IDEA配置靜態(tài)資源熱加載操作(Springboot修改靜態(tài)資源不重啟),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-10-10
  • Protostuff序列化和反序列化的使用說(shuō)明

    Protostuff序列化和反序列化的使用說(shuō)明

    今天小編就為大家分享一篇關(guān)于Protostuff序列化和反序列化的使用說(shuō)明,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-04-04
  • spring啟動(dòng)錯(cuò)誤Singleton bean creation not allowed while the singletons of this factory are indestruction

    spring啟動(dòng)錯(cuò)誤Singleton bean creation not al

    本文主要介紹了spring啟動(dòng)錯(cuò)誤Singleton bean creation not allowed while the singletons of this factory are indestruction,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • springboot業(yè)務(wù)功能實(shí)戰(zhàn)之告別輪詢websocket的集成使用

    springboot業(yè)務(wù)功能實(shí)戰(zhàn)之告別輪詢websocket的集成使用

    WebSocket使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡(jiǎn)單,允許服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于springboot業(yè)務(wù)功能實(shí)戰(zhàn)之告別輪詢websocket的集成使用,需要的朋友可以參考下
    2022-10-10
  • Java中Console對(duì)象實(shí)例代碼

    Java中Console對(duì)象實(shí)例代碼

    這篇文章主要介紹了Java中Console對(duì)象實(shí)例代碼,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-02-02
  • Java并發(fā)編程之顯示鎖ReentrantLock和ReadWriteLock讀寫鎖

    Java并發(fā)編程之顯示鎖ReentrantLock和ReadWriteLock讀寫鎖

    這篇文章主要介紹了Java并發(fā)編程之顯示鎖ReentrantLock和ReadWriteLock讀寫鎖,本文講解了ReentrantLock概況、Lock接口、Lock使用、輪詢鎖的和定時(shí)鎖、公平性、可中斷獲鎖獲取操作等內(nèi)容,需要的朋友可以參考下
    2015-04-04
  • Java mysql特殊形式的查詢語(yǔ)句詳解

    Java mysql特殊形式的查詢語(yǔ)句詳解

    這篇文章主要介紹了Java mysql特殊形式的查詢,包括子查詢和聯(lián)合查詢、自身連接查詢問(wèn)題,本文通過(guò)sql語(yǔ)句給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-02-02
  • SpringBoot中的JPA(Java?Persistence?API)詳解

    SpringBoot中的JPA(Java?Persistence?API)詳解

    這篇文章主要介紹了SpringBoot中的JPA(Java?Persistence?API)詳解,JPA用于將?Java?對(duì)象映射到關(guān)系型數(shù)據(jù)庫(kù)中,它提供了一種面向?qū)ο蟮姆绞絹?lái)操作數(shù)據(jù)庫(kù),使得開發(fā)者可以更加方便地進(jìn)行數(shù)據(jù)持久化操作,需要的朋友可以參考下
    2023-07-07
  • SpringBoot多數(shù)據(jù)源配置并通過(guò)注解實(shí)現(xiàn)動(dòng)態(tài)切換數(shù)據(jù)源

    SpringBoot多數(shù)據(jù)源配置并通過(guò)注解實(shí)現(xiàn)動(dòng)態(tài)切換數(shù)據(jù)源

    本文主要介紹了SpringBoot多數(shù)據(jù)源配置并通過(guò)注解實(shí)現(xiàn)動(dòng)態(tài)切換數(shù)據(jù)源,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08

最新評(píng)論