Spring框架中的事件(Event)机制是基于观察者模式实现的,它提供了一种简单的方式来通知应用程序中的不同部分发生了某些事情。通过Spring的事件机制,你可以在应用中发布和监听自定义事件,从而实现组件之间的松耦合通信。
一、核心概念
- ApplicationEvent:这是所有Spring事件的基类。你可以创建自己的事件类型,只需继承ApplicationEvent类,并在构造函数中传入事件源(即发生事件的对象)。
- ApplicationListener:这是一个接口,用于监听特定类型的事件。你需要实现这个接口,并重写onApplicationEvent(ApplicationEvent event)方法来处理对应的事件。Spring会自动检测并注册实现了该接口的bean作为监听器。
- ApplicationEventPublisher:这是一个接口,提供了发布事件的方法。通常,你可以通过依赖注入获取ApplicationEventPublisher的实例,或者如果你的类是一个Spring管理的bean,那么你可以实现ApplicationEventPublisherAware接口来获得一个引用。
- @EventListener:从Spring 4.2开始,你可以使用这个注解直接在方法上标注,这样就无需显式实现ApplicationListener接口了。只需要在适当的方法上添加@EventListener注解,并指定要监听的事件类型即可。
二、使用步骤
1.定义事件:创建一个继承自ApplicationEvent的类。
2.监听事件:可以有两种方式
(1)实现ApplicationListener<T>接口,其中T是你感兴趣的事件类型。
(2)或者更简便地,在任何Spring管理的bean的方法上使用@EventListener注解。
3.发布事件:在你的服务或控制器中注入ApplicationEventPublisher,然后调用其publishEvent()方法来触发事件。
三、示例
1.定义事件
package com.example.project.demos.event;
import org.springframework.context.ApplicationEvent;
public class TestEvent extends ApplicationEvent {
private String msg;
public TestEvent(Object source, String msg) {
super(source);
this.msg = msg;
}
public String getMsg(){
return msg;
}
}
2.监听事件
package com.example.project.demos.event;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;
@Component
public class TestEventListener {
@EventListener(condition = "#event.msg == 'demo'")
@Async //异步处理事件:即TestEvent的msg为demo
public void receiveMsg(TestEvent event){
System.out.println("received msg demo:"+event.getMsg());
System.out.println("event thread A:"+Thread.currentThread().getName());
}
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT, condition = "#event.msg == 'TEST'")
@Async //异步处理事件:即TestEvent的msg为TEST
public void receiveOtherMsg(TestEvent event){
System.out.println("received msg TEST:"+event.getMsg());
System.out.println("event thread B:"+Thread.currentThread().getName());
}
}
扩展1:开启异步处理事件
(1)在启动类添加注解@EnableAsync
(2)事件监听方法上添加注解@Async
@SpringBootApplication
@EnableAsync //开启异步处理
public class ProjectApplication {
public static void main(String[] args) {
SpringApplication.run(ProjectApplication.class, args);
}
}
扩展2:过滤触发监听器执行
如:@EventListener(condition = "#event.msg == 'demo'"),在代码中如果有多个过滤触发,可以实现对同一事件中不同属性触发相应的处理方法。
- condition:这是@EventListener注解的一个属性,允许你指定SpEL(Spring Expression Language)表达式。只有当这个表达式的计算结果为true时,监听器方法才会被执行。
- "#event.msg == 'demo'":这是一个SpEL表达式,用于判断是否应该执行标注了@EventListener的方法。这里的#event代表发布的事件对象,假设该事件对象有一个getMsg()方法(或直接访问的msg字段),则此表达式会检查该消息是否等于字符串"demo"。如果条件成立,即事件对象的msg属性确实为"demo",那么监听器方法将会被执行;否则,不会执行。
扩展3:@TransactionalEventListener
@TransactionalEventListener 是 Spring Framework 提供的一个注解,专门用于监听那些与事务状态相关的事件。它允许你指定事件处理器在事务生命周期的哪个阶段被触发。这个注解特别适用于那些需要确保在事务成功提交后才执行的操作,比如发送邮件、通知外部系统等。
参数 phase
- AFTER_COMMIT(默认值):当事务成功提交之后触发。
- BEFORE_COMMIT:在事务提交之前触发。
- AFTER_ROLLBACK:如果事务回滚了,则在此时触发。
- AFTER_COMPLETION:无论事务是提交还是回滚,都会触发。你可以通过观察传入的TransactionStatus来区分事务的状态。
3.发布事件
package com.example.project.demos.service;
import com.example.project.demos.DTO.User;
import com.example.project.demos.event.TestEvent;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class UserService {
@Resource
private ApplicationEventPublisher publisher;
@EventListener(ApplicationReadyEvent.class)
public void createUser(User user){
//如果调用此方法可以实现事件的发布
TestEvent event = new TestEvent(publisher,"TEST");
publisher.publishEvent(event);
//其他代码逻辑......
//TODO:
}
}