Spring 事件(Spring Events)是 Spring 框架中的一个特性,它允许应用程序中的各个部分之间进行松耦合的通信。在 Spring 中,事件通常由事件发布者发布,然后由事件监听器监听和处理。这种模型使得不同部分的逻辑可以相互独立,降低它们之间的耦合度,同时也提高了代码的可维护性和可扩展性。
SpringEvent 核心类介绍
在 Spring 框架中,事件(Event)是一种用于在应用程序中处理消息和通知的机制。当某个特定的事件发生时,应用程序中的其他部分可以监听并作出相应的响应。以下是一些与 Spring 事件相关的主要对象:
- ApplicationEvent类:
ApplicationEvent
是 Spring 事件体系的基类,用于表示应用程序中发生的事件。开发人员可以根据需要创建自定义的ApplicationEvent
子类来表示特定类型的事件。 - ApplicationEventPublisher接口:
ApplicationEventPublisher
是一个接口,定义了用于发布事件的方法。通过实现该接口,应用程序的各个部分可以发布事件,通知其他部分发生了特定的事件。 - ApplicationListener接口:
ApplicationListener
是一个接口,用于监听应用程序中发布的事件。通过实现该接口,并指定要监听的事件类型,开发人员可以编写事件监听器来处理特定类型的事件。 - @EventListener 注解:
@EventListener
是一个注解,用于标记方法作为事件监听器。通过在方法上添加@EventListener
注解,并指定要监听的事件类型,开发人员可以将方法注册为事件监听器,当相应的事件发生时,被标记的方法将被调用。 - ContextRefreshedEvent:
ContextRefreshedEvent
是 Spring 框架中的一个内置事件,表示应用程序上下文被初始化或刷新的事件。可以通过监听该事件来执行一些初始化操作。 - PayloadApplicationEvent:
PayloadApplicationEvent
是ApplicationEvent
的一个实现,它允许将一个对象作为事件的负载(payload),这样监听器可以直接访问该负载对象。
这些对象构成了 Spring 框架中事件驱动编程的基本组成部分,开发人员可以利用它们来实现事件的发布和监听,从而实现应用程序内部各个部分之间的解耦和通信。
Spring Event 案例演示(3个类快速入门)
定义一个事件
首先需要定义一个自定义事件 CustomEvent,继承ApplicationEvent,让当前CustomEvent类变成一个事件类。同时事件本身自定义了2个参数 userName,age
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.ApplicationEvent;
import java.time.Clock;
/**
* @author : zanglikun
* @date : 2024/6/16 上午11:38
* @desc : Copyright © zanglikun.com
* 定一个类CustomEvent 继承ApplicationEvent,让当前CustomEvent类变成一个事件类
*/
public class CustomEvent extends ApplicationEvent {
@Getter
@Setter
private String userName;
@Getter
@Setter
private Integer age;
// 继承ApplicationEvent必须要实现的方法
public CustomEvent(Object source) {
super(source);
}
// 继承ApplicationEvent必须要实现的方法
public CustomEvent(Object source, Clock clock) {
super(source, clock);
}
}
创建事件监听器:
接下来,自定义一个事件监听器 CustomEventListener,用于监听刚才定义的CustomEvent事件,并在监听到事件的onApplicationEvent方法执行了发送QQ消息的逻辑。
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* @author : zanglikun
* @date : 2024/6/16 上午11:46
* @desc : Copyright © zanglikun.com 实现ApplicationListener参数指定CustomEvent,
* 用来实现onApplicationEvent来执行对事件的处理
*/
@Slf4j
@Component // 不可省略
public class CustomEventListener implements ApplicationListener<CustomEvent> {
@Override
public void onApplicationEvent(CustomEvent event) {
sendQQMessage(event.getUserName());
}
public void sendQQMessage(String message) {
// todo 给QQ发送消息
log.info("给QQ发送:{}消息", message);
}
}
测试发送消息的代码:
我们使用 Spring 的事件发布者 ApplicationEventPublisher 来发布自定义的CustomEvent事件。
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author : zanglikun
* @date : 2024/6/16 上午11:52
* @desc : Copyright © zanglikun.com
*/
@Api(tags = "事件测试")
@RestController
@RequestMapping("/event/api/v1/")
public class EventController {
// 注入一个事件发布对象,用来发布事件
@Resource
private ApplicationEventPublisher eventPublisher;
@GetMapping
@ApiOperation("发送")
public String sendMessage(String msg) {
if (StringUtils.isBlank(msg)) {
msg = "前端没有输入param msg!";
}
// 构造事件对象
CustomEvent customEvent = new CustomEvent(this);
customEvent.setUserName(msg);
// 发送事件
eventPublisher.publishEvent(customEvent);
return "发送成功";
}
}
这个例子展示了 Spring 事件在真实业务中的使用。通过使用事件机制,我们可以将不同部分的逻辑解耦。
SpringEvent 事务相关
在 Spring 中,事件的发布和监听通常是在同一个事务内执行的。这意味着如果事件发布的过程中发生了事务回滚,那么对应的事件监听器中的逻辑也会被回滚。
我一开始想的是:如果A服务发送了一个事件,然后A服务的监听器里出现了异常。这样就会导致数据不一致的事务问题。这是一件很麻烦的事情。但是实际情况监听器与发送的线程一般来说是同一个,就不会有数据没回滚的问题了。如果是集群,更是如此了!
Spring 事件的应用场景包括但不限于
- 异步处理任务: 当某些任务不需要立即执行,而是可以延迟执行时,可以使用 Spring 事件来触发异步处理任务,从而提高系统的响应速度和并发能力。
- 业务流程触发: 在复杂的业务流程中,不同步骤之间可能需要进行通信和协调。通过使用 Spring 事件,可以在不同步骤之间进行通信,触发后续的业务逻辑。
- 领域事件驱动开发(Domain-Driven Design,DDD): 在领域驱动设计中,领域事件是一种描述领域中发生的事情的方式。通过使用 Spring 事件,可以将领域事件与业务逻辑解耦,从而更好地实现领域驱动设计。
- 系统集成: 在大型系统中,不同模块之间可能需要进行通信和协作。通过使用 Spring 事件,可以实现系统内部模块之间的解耦和通信。
- 日志记录和监控: 在系统中触发某些关键事件时,可以使用 Spring 事件来记录日志或进行监控,以便及时发现和解决问题。
总之,Spring 事件适用于需要实现模块之间解耦、异步处理任务、业务流程触发、领域事件驱动设计以及系统集成等场景。通过使用 Spring 事件,可以更好地组织和管理系统中的各个部分,提高系统的可维护性、可扩展性和可测试性。
关于解耦:采用的方式是:@Async
第三方平台不会及时更新本文最新内容。如果发现本文资料不全,可访问本人的Java博客搜索:标题关键字。以获取最新全部资料 ❤