提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
例如:。
提示:以下是本篇文章正文内容,下面案例可供参考
一、观察者模式是什么?
二、发布订阅模式是什么?
观察者模式
和发布订阅模式
是有一点点区别的,区别有以下几点:
- 耦合度:
观察者模式中,观察者直接与被观察者(主题)关联。被观察者通常有一个观察者列表,知道每个具体的观察者,并在状态变化时直接通知它们。
发布订阅模式中,发布者(Publisher)和订阅者(Subscriber)之间通过一个中间媒介(通常是事件总线或调度器)解耦。发布者并不直接知道订阅者,只关心发布事件。 - 通知方式:
观察者模式中,被观察者会调用每个观察者的更新方法,通常是一个统一的接口。
发布订阅模式中,事件总线负责将事件分发给所有订阅了该事件的订阅者,订阅者可以根据事件类型来过滤和处理事件。 - 消息传递:
观察者模式通常涉及一对一的通知,即被观察者只通知其已知的观察者。
发布订阅模式允许一对多的消息传递,一个发布者可以有多个订阅者,而一个订阅者也可以订阅多个发布者。 - 动态性:
观察者模式的动态性较低,观察者通常在运行时就已经与被观察者关联。
发布订阅模式更灵活,订阅者可以在运行时动态地订阅和取消订阅事件,无需修改发布者的代码。 - 控制流:
观察者模式通常在同步环境中使用,发布者直接调用观察者的更新方法。
发布订阅模式可以支持异步处理,订阅者可以在不同的线程或进程中接收和处理事件。 - 消息粒度:
观察者模式通常关注特定对象的状态变化。
发布订阅模式更倾向于处理更抽象的事件或消息,可能包含更丰富的信息。 - 可扩展性:
发布订阅模式更容易扩展,因为新的订阅者可以轻松加入,而不会影响现有发布者。 - 应用场景:
观察者模式适合于需要即时响应状态变化的场景,如UI组件与模型的同步。
发布订阅模式适用于需要解耦和异步处理的大型系统或分布式系统。
三、Spring事件监听机制
0、应用场景
- 解耦:
1、当一个操作完成后需要执行一系列后续动作,但这些动作与其他业务逻辑无关时,使用事件监听可以避免直接耦合。例如,用户注册成功后发送验证邮件或短信。
2、有一种情况,在给原系统进行架构升级时。发现有五六处甚至更多地方都用到了发短信的功能,但是发短信的功能是耦合的写到这五六个地方的。如果这个时候,发短信功能根据客户的需求进行修改,就需要改五六个地方。解决:将发短信的功能写成事件,这样只需要修改一次即可,防止出现漏改
的情况。而且事件可以更加灵活的添加到其他功能模块中。 - 异步处理:
对于耗时的操作,可以将其包装为事件,然后异步处理,以避免阻塞主线程。例如,用户上传大文件后,发布一个处理文件的事件,后台服务异步处理上传的文件。 - 模块间通信:
不同模块或服务之间可以通过发布和监听事件来通信,而不必知道对方的具体实现。例如,订单系统创建订单后,库存系统可以通过监听订单创建事件来更新库存状态。 - 事务补偿:
在分布式事务中,如果主事务成功,可以发布一个事件来触发补偿事务,确保整体业务的一致性。
1、概述
Spring的事件监听机制是基于观察者模式实现的,它允许在Spring应用上下文中,组件之间通过发布和监听事件来进行异步通信。
2、组成部分
- 事件对象(Event Object):
Spring提供了一个基础类ApplicationEvent
,它是所有自定义事件的基础。你需要创建自己的事件类,通常继承自ApplicationEvent
,并添加特定事件的数据。 - 事件监听器(Event Listener):
定义监听器有两种方式:
接口方式:实现ApplicationListener
接口,该接口有一个onApplicationEvent
方法,当监听到事件时,这个方法会被调用。
注解方式:使用@EventListener
注解在方法上,这个方法会处理特定类型的事件。 - 事件发布(Event Publishing):
要发布事件,你可以通过ApplicationContext
或ApplicationEventPublisher
接口的publishEvent
方法来发送事件实例。 - 事件广播(Event Broadcasting):
Spring使用ApplicationEventMulticaster
接口来广播事件。默认实现是SimpleApplicationEventMulticaster
,它负责找到所有监听特定事件的bean,并调用它们的事件处理方法。 - 事件注册(Event Registration):
当bean被Spring容器初始化时,如果它实现了ApplicationListener
接口或包含了@EventListener
注解的方法,那么它会被自动注册为事件监听器。 - 工作流程:
发布事件:当某个bean需要通知其他bean发生了某些事情时,它创建一个事件对象并调用publishEvent
方法。
广播事件:ApplicationEventMulticaster
接收到事件后,遍历所有已注册的监听器,调用它们的onApplicationEvent
方法或注解方法。
处理事件:监听器接收到事件后,执行相应的业务逻辑。 - 应用场景:
数据库连接关闭后通知其他组件。
请求处理完成后执行清理任务。
定期任务完成后的通知。
应用启动或关闭时的初始化和清理操作。
3、流程图
4、类图
四、代码实现
1.事件发布器
首先,springframework.context
是Spring框架的一个重要模块,它提供了与应用程序上下文相关的服务,包括组件扫描、依赖注入、事件发布、国际化和资源处理等功能。在Spring框架中,ApplicationContext
是这个模块的核心接口,它是bean工厂的扩展,增加了加载配置元数据、事件发布以及与其他Spring特性集成的能力。
事件发布器
类MyBean 实现了ApplicationEventPublisherAware
接口,关于ApplicationEventPublisherAware
接口,这是Spring框架提供的一个回调接口,允许任何实现了该接口的bean获取到ApplicationEventPublisher
的引用。ApplicationEventPublisher
接口用于发布应用程序事件,这些事件可以被其他bean监听和处理。当一个bean实现了ApplicationEventPublisherAware
,Spring容器会在初始化该bean时自动调用其setApplicationEventPublisher()
方法,传入事件发布器的实例。
事件发布器
类MyBean 的代码如下(示例):
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
@Service
public class MyBean implements ApplicationEventPublisherAware {
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
public void someMethod() {
// 在业务逻辑中,当需要触发一个事件时,可以使用publisher
CustomEvent customEvent = new CustomEvent(this);
publisher.publishEvent(customEvent);
}
}
class CustomEvent extends ApplicationEvent {
// 事件的具体实现
// ...
}
2.创建事件类
代码如下(示例):
import org.springframework.context.ApplicationEvent;
import java.time.Clock;
import java.util.List;
/**
* @author ZY.xxx
* @date 20xx/xx/xx xx:xx
* 作废事件
**/
public class CancelEvent extends ApplicationEvent {
private Param1 param1;
private List<Param2> param2List;
public CancelEvent(Object source) {
super(source);
}
public CancelEvent(Object source, Param1 param1, List<Param2> param2List) {
super(source);
this.param1= param1;
this.param2List= param2List;
}
// 两个变量参数的getter和setter方法
// ...
}
3.创建事件监听类(注解的方式实现)
代码如下(示例):
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
1. @author ZY.xxx
2. @date 20xx/xx/xx xx:xx
3. xx事件监听器
**/
@Component
public class EventHandler {
@Autowired
private XXXService xxxService;
@Autowired
private RedisService redisService;
@Autowired
private CommonService commonService;
@EventListener
public void onEnvet(CommonEvent event) {
//公共事件逻辑
// ...
}
@EventListener
public void onEnvet(CancelEvent event) {
//取消事件逻辑
// ...
//监听器监听到事件的发布,可以获取到事件中的全部信息
event.getParam1();
event.getParam2List();
}
@EventListener的注意点
@EventListener
是Spring框架中用于事件监听的一个注解,它的主要作用是将一个方法标记为事件处理器,用于响应特定类型的事件。
@EventListener
提供了一种声明式的事件处理方式,使得事件驱动的编程模型在Spring应用中变得简单和灵活
- 事件发布
发布器发布后 - 事件处理
Spring容器在初始化时,会扫描带有@EventListener注解
的方法。这些方法必须属于Spring管理的bean(注入到spring上下文中的类)。
每个@EventListener注解
的方法都会关联一个或多个事件类型。当事件被发布时,Spring会检查当前事件的类型是否与注解中指定的事件类型匹配。 - 条件触发
@EventListener
的condition
属性允许通过SpEL表达式控制事件处理的条件。如果表达式评估结果为真,事件处理方法才会被执行。 - 异步处理、
默认情况下,事件处理是同步的,这意味着事件处理器方法会在发布事件的线程中执行。但通过@Async
注解,可以将事件处理转换为异步执行。 - 事件分组:
使用@Order
注解可以指定事件处理方法的执行顺序,较低的数字表示优先级较高。 - 性能优化:
Spring 4.2及以上版本引入了事件多路复用(multi-casting),通过缓存事件处理器的引用来提高性能,避免每次事件发布时都要查找处理器。
3.创建事件监听类(实现ApplicationListener接口)
代码如下(示例):
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
public class CustomEventListener implements ApplicationListener<CancelEvent> {
@Override
public void onApplicationEvent(CancelEvent event) {
// 在这里处理CancelEvent
System.out.println("Received CancelEvent : " + event.getMessage());
// 实现你的业务逻辑
}
}
4.应用
可以在项目的任何地方不在改动源代码的基础上异步的执行事件event的功能
代码如下(示例):
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Service
public class A implements B {
@Override
public void method1(Param param) {
//原逻辑代码
CancelEvent cancelEvent= new CancelEvent(param.getID(), param, paramList);
this.eventPublisher.publishEvent(cancelEvent);
}
}
个人理解:
- 使用时,先创建new一个事件对象。
- 注入时间发布器对象
EventPublisher
,这个类主要是实现了ApplicationEventPublisherAware
(原理见上),调用发布器发布事件的方法,这样事件就可以被其他bean监听和处理。 - 事件监听器(打了
@EventListener
注解或者实现ApplicationListener
接口的类)会立马监听到第2步发布的事件,来执行监听器中的业务逻辑。(实现了事件逻辑与原逻辑解耦、独立的对事件中的逻辑进行统一的修改)
总结
提示:这里对文章进行总结:
例如:。