欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

springboot?publish?event?事件機制demo分享

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

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

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

事件機制

  • 需要自定義一個事件類繼承ApplicationEvent;
  • 需要自定義一個監(jiān)聽器類實現(xiàn)ApplicationListener接口,或普通類的方法中使用@EventListener注解;
  • 使用默認發(fā)布器ApplicationEventPublisher發(fā)布即可;
  • 事件類不需要注入到IOC;監(jiān)聽器需要注入到IOC;ApplicationEventPublisher用Autowired注入進來即可;
  • 默認情況下,事件發(fā)布與執(zhí)行是同步的,事件執(zhí)行完畢,發(fā)布者才會執(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 {
    /**
     * 事件機制:
     * 需要自定義一個事件類繼承ApplicationEvent;
     * 需要自定義一個監(jiān)聽器類實現(xiàn)ApplicationListener接口,或普通類的方法中使用@EventListener注解;
     * 使用默認發(fā)布器ApplicationEventPublisher發(fā)布即可;
     * 事件類不需要注入到IOC;監(jiān)聽器需要注入到IOC;ApplicationEventPublisher用Autowired注入進來即可;
     */


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

    /**
     * 測試類
     */
    @Test
    public void publishTest() throws InterruptedException {
        Task task = new Task();
        task.setId(1L);
        task.setTaskName("測試任務(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ù)就是一個普通的類,用來保存你要發(fā)布事件的內(nè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所識別
 */
@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)聽器需要實現(xiàn)org.springframework.context.ApplicationListener,并且需要注入到容器之中。
 */
@Component
@Slf4j
class MyEventListenerA implements ApplicationListener<MyEvent> {
    /**
     * 監(jiān)聽方式1:實現(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此時完成任務(wù)");

    }
}

@Component
@Slf4j
class MyEventListenerB implements ApplicationListener<MyEvent> {
    /**
     * 監(jiān)聽方式2:接口和注解混合使用
     * 但此時 @EventListener不能與注解@Async在同一個類中使用,會報錯,至于為什么,不知道;
     * 需要使用Component注入IOC
     */
    //@Async//加上這個,@EventListener的方法就會報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此時完成任務(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)聽器不需要實現(xiàn)任何接口
     * 需要使用Component注入IOC
     */
    @EventListener
    public void someMethod(MyEvent event) throws InterruptedException {
        Thread.sleep(1000);
        log.info("監(jiān)聽器@EventListenerC收到={}", event.getTask());
    }
}

運行日志:

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=測試任務(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=測試任務(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":"測試任務(wù)"}
2020-11-30 18:13:59.921  INFO 19776 --- [           main] com.example.controller.MyEventListenerB  : 監(jiān)聽器B此時完成任務(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":"測試任務(wù)"}
2020-11-30 18:14:03.913  INFO 19776 --- [         task-1] com.example.controller.MyEventListenerA  : 監(jiān)聽器A此時完成任務(wù)
2020-11-30 18:14:09.958  INFO 19776 --- [       Thread-3] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'

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

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

與上例不同之處

  • 使用ApplicationContext發(fā)布事件,ApplicationContext實現(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;
    }
}

運行日志:

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ā)送后,會等待事件執(zhí)行完畢,因此他們是同步的。若想異步執(zhí)行事件,可以把@Async加到監(jiān)聽方法上;

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

相關(guān)文章

  • 老生常談Scanner的基本用法

    老生常談Scanner的基本用法

    下面小編就為大家?guī)硪黄仙U凷canner的基本用法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • IDEA配置靜態(tài)資源熱加載操作(Springboot修改靜態(tài)資源不重啟)

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

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

    Protostuff序列化和反序列化的使用說明

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

    spring啟動錯誤Singleton bean creation not al

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

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

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

    Java中Console對象實例代碼

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

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

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

    Java mysql特殊形式的查詢語句詳解

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

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

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

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

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

最新評論