一、核心概念与模型
Spring 的事件机制是观察者模式(也叫发布-订阅模型)的一种典型实现。它主要由三个核心部分组成:
事件 (Event): 承载信息的对象,通常是某种状态变化的通知。可以是继承
ApplicationEvent
的类,也可以是任何普通的 Java 对象(POJO)。发布者 (Publisher): 负责产生并发布事件的组件。它通过
ApplicationEventPublisher
来发布事件。监听器 (Listener): 负责接收和处理事件的组件。它监听特定类型的事件并做出响应。
工作流程:发布者发布一个事件 -> Spring 的 ApplicationContext
(作为事件广播器)接收事件 -> 广播器将事件通知给所有注册的、对该事件感兴趣的监听器 -> 监听器执行自身的业务逻辑。
二、详细用法与步骤
我们将通过一个经典的业务场景——用户注册成功后,发送邮件和短信——来演示每一步的用法。
第 1 步:定义事件 (Event)
事件是一个简单的 POJO,用于封装需要传递的数据。自 Spring 4.2 以后,不再需要强制继承 ApplicationEvent
。
package jnpf.model.cultivate.event;
import lombok.Getter;
import org.springframework.context.ApplicationEvent;
@Getter
public class JnpfApplicationEvent<T> extends ApplicationEvent {
private final T data;
public JnpfApplicationEvent(T source) {
super(source);
this.data = source;
}
}
第 2 步:发送消息
SpringContext.getApplicationContext().publishEvent(new JnpfApplicationEvent<>(
CourseEventDTO.builder()
.courseIds(List.of(ftbCultivateCourseDTO.getCourseId()))
.userIds(new ArrayList<>())
.whetherToChange(true).build()));
第 3 步:实现监听器 (Listener)
package jnpf.cultivate.event;
import jnpf.model.cultivate.event.JnpfApplicationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;
/**
* 事件处理程序
*
* @author fantaibao
* @date 2023/12/26
*/
@Component
public class EventHandler {
@Resource
private List<JnpfApplicationEventService> jnpfApplicationEventServices;
@EventListener(value = JnpfApplicationEvent.class)
public <T> void courseEvent(JnpfApplicationEvent<T> jnpfApplicationEvent) {
Object data = jnpfApplicationEvent.getData();
// 事件处理分发
Optional<JnpfApplicationEventService> first = jnpfApplicationEventServices.stream()
.filter(t -> t.isSupportedCourseEvent(data)).findFirst();
first.ifPresent(jnpfApplicationEventService -> jnpfApplicationEventService.handlerCourseEvent(data));
}
}
第 4 步:创建事件处理类接口
package jnpf.cultivate.event;
public interface JnpfApplicationEventService {
/**
* 是否支持此事件
*
* @param event 事件
* @return boolean
*/
boolean isSupportedCourseEvent(Object event);
/**
* 处理事件
*
* @param courseEvent 事件入参
*/
void handlerCourseEvent(Object courseEvent);
}
第 5 步:事件处理类impl
@Component
@RequiredArgsConstructor
public class JnpfApplicationEventCourseService implements JnpfApplicationEventService {
@Override
public boolean isSupportedCourseEvent(Object event) {
return event instanceof CourseEventDTO;
}
@Override
public void handlerCourseEvent(Object courseEvent) {
CourseEventDTO courseEventDTO = (CourseEventDTO) courseEvent;
if (CollUtil.isEmpty(courseEventDTO.getCourseIds())) {
return;
}
List<String> userIds = courseEventDTO.getUserIds();
//处理逻辑
}