Spring Event事件处理
Spring 事件处理基于 Java 观察者模式扩展。Spring 应用上下文中发布了各种事件,此外 Spring 还允许我们发送和处理自定义的事件,本篇将对 Spring 的事件机制使用进行详细介绍。
基础使用
1. 定义事件
定义事件:需要继承ApplicationEvent,例如:
public class UserRegisteredEvent extends ApplicationEvent {
public UserRegisteredEvent(User user) {
super(user); // 调用父类构造器,传入事件源
}
public User getUser() {
return (User) getSource();
}
}
2. 定义事件发布器
定义事件发布器:使用ApplicationEventPublisherAware获取ApplicationEventPublisher,例如:
@Component
public class UserEventPublisher implements ApplicationEventPublisherAware {
private ApplicationEventPublisher applicationEventPublisher;
public void publishUserRegistered(User user) {
applicationEventPublisher.publishEvent(new UserRegisteredEvent(user));
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
}
3. 定义事件监听器
定义事件监听器可以通过两种方式:
- 实现ApplicationListener接口,监听特定事件,例如:
@Component
public class UserEventListener implements ApplicationListener<UserRegisteredEvent> {
@Override
public void onApplicationEvent(UserRegisteredEvent event) {
User user = event.getUser();
// 对user对象进行相关处理...
}
}
- 使用@EventListener注解直接标注在方法上,该方法会自动注册为事件监听器,无需实现ApplicationListener接口。
@Component
public class UserEventListener {
@EventListener
public void onUserRegistered(UserRegisteredEvent event) {
// 处理逻辑
}
}
4.发布与订阅事件
注入时间发布器进行时间发布
@Autowired
private UserEventPublisher userEventPublisher;
@Autowired
private UserService userService;
public void registerUser(User user) {
userService.register(user);
userEventPublisher.publishUserRegistered(user);
}
高级使用
异步事件
使用@Async注解实现异步事件
- 在项目主类上加入@EnableAsync注解
- 改造监听器,在原来的方法上加入@Async注解
@Component
public class UserEventListener {
@Async
@EventListener
public void onUserRegistered(UserRegisteredEvent event) {
// 处理逻辑
}
}
事件过滤
如果我们想对事件进行限制,某一部分满足条件的事件才发送邮件,可以使用condition属性来指定限制的条件。
@Component
public class UserEventListener {
@EventListener(condition = "#event.userId > 5")
public void onUserRegistered(UserRegisteredEvent event) {
// 处理逻辑
}
}
顺序监听
每个事件都可以定义多个监听器,默认情况下监听器执行的顺序是未知的。可以使用 @Order
注解来指定监听器的权重,来确定监听器的执行顺序。
@Component
public class UserEventListener {
@Order(1)
@EventListener
public void onUserRegistered(UserRegisteredEvent event) {
// 处理逻辑
}
@Order(2)
@EventListener
public void onUserRegistered(UserRegisteredEvent event) {
// 处理逻辑
}
@Order(3)
@EventListener
public void onUserRegistered(UserRegisteredEvent event) {
// 处理逻辑
}
}
事务处理
在Spring中,可以使用@TransactionalEventListener
注解对监听器进行标注,使用此注解,被标注的方法将被纳入到事务管理的范围。此注解是@EventListener的扩展,它允许你将事件的监听绑定到某个事务阶段。可以通过phase属性对事务阶段进行设置。下面是phase可设置的所有事务阶段:
- 1、AFTER_COMMIT(默认值),用于在事务成功完成后触发事件
- 2、AFTER_ROLLBACK,用于事务回滚是触发事件
- 3、AFTER_COMPLETION,用于事务完成后触发事件(AFTER_COMMIT和AFTER_ROLLBACK的一种模糊表述)
- 4、BEFORE_COMMIT,用于事务提交前触发事件
@Component
public class UserEventListener {
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void onUserRegistered(UserRegisteredEvent event) {
// 处理逻辑
}
}
自定义@Async异步线程池
在 Spring 中,通过 @Async
注解可以实现异步方法调用,但默认情况下它使用的是一个简单的线程池。如果你想自定义线程池来管理异步任务,可以按照以下步骤操作:
- 创建自定义线程池: 首先,你需要创建一个自定义的线程池,可以使用 Java 提供的
ExecutorService
接口的实现类,如ThreadPoolExecutor
。 - 配置线程池: 在 Spring 配置中,你可以使用
@Bean
注解将你的自定义线程池注入到 Spring 容器中。你可以在配置类中创建这个 Bean。 - 使用自定义线程池: 在异步方法上添加
@Async
注解时,通过value
属性指定要使用的线程池的 Bean 名称,以让 Spring 使用你自定义的线程池。
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Bean(name = "customExecutor")
public Executor customExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(30);
executor.setThreadNamePrefix("CustomExecutor-");
executor.initialize();
return executor;
}
}
然后,在需要异步执行的方法上使用 @Async
注解,并指定使用的线程池的 Bean 名称:
@Component
public class UserEventListener {
@Async("customExecutor")
@EventListener
public void onUserRegistered(UserRegisteredEvent event) {
// 处理逻辑
}
}
Spring系统事件
在Spring中,有一些系统事件,都是基于ApplicationEvent扩展的,可以自己看实现ApplicationEvent的实现类来查看系统默认事件。下图中ApplicationContextEvent是Spring上下问的一些事件;SpringApplicationEvent是Spring Boot中的一些事件。
如果需要我们可以监听Spring系统事件来实现一些功能。正常只有框架需要,业务开发不需要。
自定义ApplicationEventMulticaster
ApplicationEventMulticaster是spring中事件广播器接口,负责事件的广播发布。AbstractApplicationContext
中使用initApplicationEventMulticaster()
初始化事件广播器。自定义 ApplicationEventMulticaster
可以实现以下功能:
- 自定义事件派发策略: 通过自定义
ApplicationEventMulticaster
,你可以实现自己的事件派发策略。默认情况下,Spring 使用SimpleApplicationEventMulticaster
,但你可以根据需要创建一个自定义的派发策略,例如,你可以实现异步事件派发,或者基于条件的事件派发策略。 - 集成消息中间件: 如果你想将 Spring 事件和消息中间件(如 RabbitMQ、Kafka 等)集成,可以自定义
ApplicationEventMulticaster
来实现这个集成。这样,你就可以在事件发布时将事件转换为消息,并通过消息中间件进行分发。 - 事件过滤和处理顺序控制: 通过自定义
ApplicationEventMulticaster
,你可以添加事件过滤器,只有符合特定条件的事件才会被派发。你还可以控制事件监听器的处理顺序,确保监听器按照你定义的顺序依次处理事件。 - 多线程事件派发: 默认情况下,Spring 事件是同步派发的。但你可以通过自定义
ApplicationEventMulticaster
来实现异步事件派发,从而在事件发布时启动新的线程来处理事件。 - 与其他框架集成: 自定义
ApplicationEventMulticaster
还可以用于将 Spring 事件与其他框架的事件机制集成,从而实现不同框架之间的事件通信。
需要注意的是,自定义 ApplicationEventMulticaster
是一个高级用法,一般情况下使用 Spring 提供的默认实现已经足够满足需求。但在某些特定情况下,自定义 ApplicationEventMulticaster
可以提供更多的灵活性和定制性,以满足复杂的应用场景。
例如,自定义ApplicationEventMulticaster实现异步事件派发:
@Configuration
public class AsyncSpringEventConfig {
@Bean(name = "applicationEventMulticaster")
public ApplicationEventMulticaster applicationEventMulticaster(){
SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
multicaster.setTaskExecutor(new SimpleAsyncTaskExecutor());
return multicaster;
}
}