Spring Event 事件发布/监听机制 详解并使用

Spring的事件监听(也叫事件驱动)是观察者模式的一种实现,只要是观察者模式,就含有主题(针对该主题的事件),发布者(发布主题或事件),订阅者(监听主题的人)。有三个部分组成,事件(ApplicationEvent)、监听器(ApplicationListener)和事件发布操作。

作用:

使用事件机制我们可以将相互耦合的代码解耦,从而方便功能拓展和调整。

1. 观察者模式简介

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。

比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。

img

2. 观察者模式角色
  • Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。

  • ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。

  • Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。

  • ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。

3. 事件机制实现方式

实现Spring事件机制主要有4个类:

  1. ApplicationEvent:事件,每个实现类表示一类事件,可携带数据。
  2. ApplicationListener:事件监听器,用于接收事件处理时间。
  3. ApplicationEventMulticaster:事件管理者,用于事件监听器的注册和事件的广播。
  4. ApplicationEventPublisher:事件发布者,委托ApplicationEventMulticaster完成事件发布。
3.1 ApplicationEvent

ApplicationEvent:应用事件,职责为定义业务

Spring 提供了一个继承于java.util.EventObject 类的ApplicationEvent的的抽象类,并提供了应用上线文事件的抽象实现ApplicationContextEvent 下面的容器关闭、刷新、启动、停止等容器事件 以及RequestHandledEvent(http 请求处理完成事件),可自定义
事件(只需要实现ApplicationEvent 抽象类定义有参构造函数即可,source表示事件源,( 可按照自己的需求制定)

自定义event代码实例:

public class TestEvent extends ApplicationEvent {
    private String message;

    public TestEvent(Object source, String message) {
        super(source);
        this.message = message;
    }

    public TestEvent(String message) {
        super(message);
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
3.2 ApplicationListener

ApplicationListener:事件监听器,职责为处理事件广播器发布的事件。

Spring提供了继承于java.util.EventListener接口的应用监听器接口, ApplicationListener,此接口源码:

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	/**
	 * Handle an application event.
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);

}

并提供了两个实现:SmartApplicationListener和GenericApplicationListener接口

事件机制监听的方式有两种:

  1. 实现ApplicationListener接口
  2. EventListener注解形式

代码实例:

@Log4j2
@Component
public class AEventListener implements ApplicationListener<TestEvent> {
    @Override
    public void onApplicationEvent(TestEvent event) {
        //逻辑处理
    }
}
@Log4j2
@Component
public class AEventListener implements ApplicationListener<TestEvent> {
    @Async
    @EventListener
    public void listener(TestEvent event) throws InterruptedException {
        Thread.sleep(2000);
        log.info("监听到数据:{}", event.getMessage());
    }
}
3.2.1 SmartApplicationListener

提供了监听器对泛型事件的支持,spring3.0 添加的

源码:

public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
    boolean supportsEventType(Class<? extends ApplicationEvent> var1);
    boolean supportsSourceType(Class<?> var1);
}
3.2.2 GenericApplicationListener

增强对泛型事件的支持(支持泛型方式不同与SmartApplicationListener),spring4.2 添加的。

源码:

public interface GenericApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
    boolean supportsEventType(ResolvableType var1);
    boolean supportsSourceType(Class<?> var1);
}
3.3 ApplicationEventMulticaster

事件广播器,职责为将EventPubsher(事件发布者)发布的event 广播给事件EventListener(事件监听器)。

Spring提供了默认的实现SimpleApplicationEventMulticaster,如果用户没有配置自定义事件广播器,
则会默认使用SimpleApplicationEventMulticaster作为事件广播器。在容器刷新的过程中会实例化、初始化事件广播器。

3.4 ApplicationEventPublisher

事件发布者,职责为发布事件。
spring的ApplicationContext 本来就实现了ApplicationEventPublisher接口,因此应用上下文本来就是
一个事件发布者,在AbstractApplicationContext中实现了事件发布的业务。

如何发布事件呢

3.4.1 发布方式1

直接注入ApplicationContext:

@Autowired
private ApplicationContext applicationContext;
applicationContext.publishEvent();
3.4.2 发布方式2

直接注入ApplicationEventPublisher:

@Autowired
private ApplicationEventPublisher applicationEventPublisher;
applicationEventPublisher.publishEvent(myEvent)
3.4.3 发布方式3
@Service
public class PublishEvent implements ApplicationEventPublisherAware {
    public static ApplicationEventPublisher eventPublisher = null;
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        eventPublisher.publishEvent("123");
    }
}
4. 代码实现
4.1 创建事件
public class TestEvent extends ApplicationEvent {
    private String message;

    public TestEvent(String message) {
        super(message);
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

如定义一个事件,对一个字符型数据处理。

4.2 创建发布者
@Service
public class PublishEvent {
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    public void publish(String message) {
        applicationEventPublisher.publishEvent(new TestEvent(message));
    }
}
4.3 创建监听者
@Log4j2
@Component
public class AEventListener {
    @EventListener
    public void listener(TestEvent event) {
        log.info("监听到数据1:{}", event.getMessage());
    }
}

调用接口

@RequestMapping("pub")
public void pub() {
    for (int i = 0; i < 5; i++) {
        publishEvent.publish("你若为我繁华,你好呀:" + (i + 1));
    }
}

事件监听器默认是同步阻塞的

这里你会不会有疑问,啥是同步阻塞呢,我这里举一个例子来说明:

在这里插入图片描述

我一次创建5个事件,调整监听处理代码

@Log4j2
@Component
public class AEventListener {
    @Async
    @EventListener
    public void listener(TestEvent event) throws InterruptedException {
        Thread.sleep(2000);
        log.info("监听到数据:{}", event.getMessage());
    }
}

sleep2秒在执行

看效果:
在这里插入图片描述
在这里插入图片描述

就类似于:吃饭和看电视,同步阻塞就是吃完饭才开始看电视,同一时间只做一件事情。

4.4 开启异步:

启动类增加此注解,开启异步支持。

@EnableAsync

在这里插入图片描述

方法增加@Async注解,表示该方法为异步方法。重启再次调用:
在这里插入图片描述

异步执行。

  • 32
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
Spring EventSpring框架中的一种实现观察者模式的机制。它的主要应用是实现程序解耦,通过事件的广播形式来实现不同组件之间的通信。 在Spring中,Event的实现方式是通过使用继承自java.util.EventObject类的ApplicationEvent抽象类。Spring提供了一些已经定义好的应用上下文事件的实现,如容器关闭、刷新、启动、停止等事件,以及RequestHandledEvent(HTTP请求处理完成事件)。同时,我们也可以自定义事件,只需要实现ApplicationEvent抽象类并定义带参数的构造函数即可,其中source表示事件源,根据自己的需求进行制定。 在实现中,我们可以通过@Configuration注解来标识一个类为配置类,并使用@EventListener注解来标识一个方法为事件处理方法。在事件处理方法中,可以根据不同的事件类型进行处理,例如打印出事件的消息内容。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [SpringEvent](https://blog.csdn.net/weixin_45874214/article/details/126167211)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [Spring Event 事件发布/监听机制 详解使用](https://blog.csdn.net/qq_37758497/article/details/118863308)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的蚂蚁【你若】

如果帮助到了您,一分也是爱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值