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实现类有很多:

其中: 

Spring提供5种标准的事件监听:
上下文更新事件(ContextRefreshedEvent):
该事件会在ApplicationContext被初始化或者更新时发布。
也可以在调用ConfigurableApplicationContext接口中的refresh()方法时被触发。
上下文开始事件(ContextStartedEvent):
当容器ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
上下文停止事件(ContextStoppedEvent):
当容ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
上下文关闭事件(ContextClosedEvent):
当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
请求处理事件(RequestHandledEvent):
在Web应用中,当一个http请求(request)结束触发该事件。

Spring Boot扩展了Spring的ApplicationContextEvent,提供了四种事件:
ApplicationStartedEvent :
spring boot启动开始时执行的事件
ApplicationEnvironmentPreparedEvent:
spring boot 对应Enviroment已经准备完毕,但此时上下文context还没有创建。
ApplicationPreparedEvent:
spring boot上下文context创建完成,但此时spring中的bean是没有完全加载完成的。
ApplicationFailedEvent:
spring boot启动异常时执行事件

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博客

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值