Spring事件发布订阅ApplicationEvent、ApplicationEventPublisher、ApplicationListener……

目录

概念

1.ApplicationEvent

2.ApplicationEventPublisher

3.ApplicationEventPublisherAware

4.ApplicationListener

具体使用

1.自定义事件MyEvent.java

2.自定义事件发布工具MyPublishAware.java

3.自定义两个事件监听器MyListenner.java(实现接口方式)和MyListennerTwo.java(注解方式)

参考文章


概念

事件的发布者发布事件,事件的监听者对对应的事件进行监听,当监听到对应的事件时,就会触发调用相关的方法。因此,在事件处理中,事件是核心,是事件发布者和事件监听者的桥梁。

Spring 是基于Observer模式(java.util包中有对应实现)提供了针对Bean的事件发布和订阅功能。
Spring中相关的主要有3个接口和1个抽象类:

public abstract class ApplicationEvent extends EventObject{
public interface ApplicationEventPublisher{
public interface ApplicationEventPublisherAware extends Aware{
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener{

1.ApplicationEvent

ApplicationEvent继承自JavaSE中的EventObject,我们在使用的时候可以继承这个抽象类来定义事件,进行信息的传递,因为ApplicationListener只接受ApplicationEvent或者他的子类。

Spring自定义的ApplicationEvent实现类有很多:

其中: 

1)ContextRefreshedEvent:当ApplicationContext初始化或者刷新时触发该事件。

2)ContextClosedEvent:当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。

3)ContestStartedEvent:当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。

4)ContestStopedEvent:当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。

5)ApplicationContextEvent 这个是平时经常用到的。 

2.ApplicationEventPublisher

事件的发布接口,通过publishEvent(ApplicationEvent event)方法来发布消息。

3.ApplicationEventPublisherAware

通过这个接口的void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher)方法,将ApplicationEventPublisher注入进去,来进行消息通知。

4.ApplicationListener

监听器接口,ApplicationListener中的void onApplicationEvent(E event)来接收消息事件,进行消息处理。通过源代码发现,事件E需要是ApplicationEvent或者ApplicationEvent的子类。

具体使用

1.自定义事件MyEvent.java

package com.genertech.plm.aia.portaladmin.test;

import org.springframework.context.ApplicationEvent;

/**
 * @author: huo.qw
 * @createTime: 2024/01/16 下午 08:17
 * @description:
 * @version: v1.0
 */
public class MyEvent extends ApplicationEvent {
  // 也可以是对象等其它数据,也可以不传递数据
  private String words;

  public MyEvent(Object source, String words) {
    super(source);
    this.words = words;
  }

  public String getWords() {
    return words;
  }

  public void setWords(String words) {
    this.words = words;
  }
}

2.自定义事件发布工具MyPublishAware.java

// 不支持异步,sayHello()发布事件后会等待所有监听器执行完(多个监听器之间也是串行执行的)才会继续执行sayHello()以下的代码。
// 若要支持,可以在启动类加@EnableAsync,在监听器的onApplicationEvent方法、
// 或者@EventListener(MyEvent.class)标注的方法加@Async注解实现。

package com.genertech.plm.aia.portaladmin.test;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * @author: huo.qw
 * @createTime: 2024/01/16 下午 08:33
 * @description:
 * @version: v1.0
 */
@Component
@EnableScheduling // 开启定时任务
@Slf4j
public class MyPublishAware implements ApplicationEventPublisherAware {
  private ApplicationEventPublisher applicationEventPublisher;

  @Override
  public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
    this.applicationEventPublisher = applicationEventPublisher;
  }

  public void sayHello(MyEvent myEvent) {
    this.applicationEventPublisher.publishEvent(myEvent);
  }

  // 通过定时任务来测试[发布事件]
  @Scheduled(fixedRate = 10000 * 1)
  public void tryTest() {
    MyEvent myEvent = new MyEvent(this, new String("hello World!"));
    sayHello(myEvent);

    // 不支持异步,sayHello()发布事件后会等待所有监听器执行完(多个监听器之间也是串行执行的)才会继续执行sayHello()以下的代码。
    // 若要支持,可以在启动类加@EnableAsync,在监听器的onApplicationEvent方法、
    // 或者@EventListener(MyEvent.class)标注的方法加@Async注解实现。
    log.info(Thread.currentThread().getName()+"测试是否支持异步");
  }
}

3.自定义两个事件监听器MyListenner.java(实现接口方式)和MyListennerTwo.java(注解方式)

package com.genertech.plm.aia.portaladmin.test;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 * @author: huo.qw
 * @createTime: 2024/01/16 下午 08:34
 * @description:
 * @version: v1.0
 */
@Component
@Slf4j
public class MyListenner implements ApplicationListener<MyEvent> {
  //如果实现的是implements ApplicationListener<ApplicationEvent>,则
  //public void onApplicationEvent(ApplicationEvent e) {会监听到所有
  //继承了ApplicationEvent抽象类的事件,其中包括MyEvent事件.

  @Override
  //@EventListener(MyEvent.class)
  public void onApplicationEvent(MyEvent e) {
    log.info(Thread.currentThread().getName()+"MyListennerOne订阅接收到的数据为:" + e.getWords());
    try {
      Thread.sleep(5000L);
    } catch (InterruptedException interruptedException) {
      interruptedException.printStackTrace();
    }
  }
}
package com.genertech.plm.aia.portaladmin.test;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

/**
 * @author: huo.qw
 * @createTime: 2024/01/17 下午 03:39
 * @description:
 * @version: v1.0
 */
@Component
@Slf4j
public class MyListennerTwo {

  @EventListener(MyEvent.class)
  public void methodName(MyEvent e) {
    log.info(Thread.currentThread().getName()+"MyListennerTwo订阅接收到的数据为:" + e.getWords());
    try {
      Thread.sleep(5000L);
    } catch (InterruptedException interruptedException) {
      interruptedException.printStackTrace();
    }
  }
}

参考文章

Spring 事件发布订阅_spring事件发布订阅-CSDN博客

spring中的发布订阅_spring 订阅发布-CSDN博客

Spring Event事件用法 Spring Boot Event事件发布和订阅 Spring Event事件发布 Spring Event事件订阅_springboot 事件发布订阅-CSDN博客