Spring Event使用小结
1、概览
Spring Events 是Spring Framework的一部分,但在应用程序中并不经常使用,甚至被忽略。然而,Spring的Application拥有强大的事件发布并注册事件监听器的能力,它拥有一套完整的事件发布与处理机制。Spring 4.2开始引入@EventListener注解来监听具体类型的事件,它的出现,消除了使用Spring定义一个事件监听器的复杂操作。仅仅通过一个简单的注解,就可以完成一个监听器的定义,你不需要额外的进行其他的配置;这简直太棒了。在Spring Framework中,事件的发布是由ApplicationContext提供的,如果想完成一个完整的面向事件(也称为事件驱动编程)编程,你需要遵循以下三个基本的原则:
1、定义一个事件,且扩展ApplicationEvent
2、事件发布者应该注入一个ApplicationEventPublisher对象
3、监听器实现ApplicationListener接口或者使用@EventListener注解
2、简单实践
2.1、创建自定义事件,继承ApplicationEvent
public class CustomSpringEvent extends ApplicationEvent {
private String message;
public CustomSpringEvent(Object source, String message) {
super(source);
this.message = message;
}
public String getMessage() {
return message;
}
}
2.2、创建事件发布者应该注入一个ApplicationEventPublisher对象
@Component
public class CustomSpringEventPublisher {
private final ApplicationEventPublisher applicationEventPublisher;
public CustomSpringEventPublisher(final ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
public void publishCustomEvent(final String message) {
System.out.println("Publishing custom event. ");
this.applicationEventPublisher.publishEvent(new CustomSpringEvent(this, message));
}
}
2.3、创建监听器实现ApplicationListener接口或者使用@EventListener注解
@Component
public class CustomSpringEventListener implements ApplicationListener<CustomSpringEvent> {
@Override
public void onApplicationEvent(CustomSpringEvent event) {
System.out.println("Received spring custom event - " + event.getMessage());
}
}
或
@Component
public class CustomSpringEventListener {
@EventListener(value = CustomSpringEvent.class)
public void onApplicationEvent(CustomSpringEvent event) {
System.out.println("Received spring custom event - " + event.getMessage());
}
}
3、进阶
3.1、处理方式
默认使用同步处理的方式,若需实现监听器异步处理我们可以结合@Async和@EnableAsync注解完成
启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
@EnableAsync
public class BootstrapApplication {
public static void main(String[] args) {
SpringApplication.run(BootstrapApplication.class, args);
}
}
事件监听器
@Component
public class CustomSpringEventListener {
@Async
@EventListener(value = CustomSpringEvent.class)
public void onApplicationEvent(CustomSpringEvent event) {
System.out.println("Received spring custom event - " + event.getMessage());
}
}
3.2、事务事件
Spring 事件可以和事务一起使用,但是可能会出现下面这种异常情况。例如,用户注册成功后发布通知事件,但在后续的事务处理中处理异常导致事务回滚,会出现用户收到注册成功短信但实际没有注册成功。最佳方式是将事务处理逻辑和事件发布拆分,避免上述异常场景。
当然也可以使用 TransactionalEventListener 指定和事务执行的顺序关系
@Override
@Transactional(rollbackFor = Exception.class)
public void doSomething() {
// 1、处理业务
// 2、业务处理成功
// 3、事件发布
// 4、事务回滚
}
事件监听
@Component
public class CustomSpringEventListener {
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
@EventListener(value = CustomSpringEvent.class)
public void onApplicationEvent(CustomSpringEvent event) {
System.out.println("Received spring custom event - " + event.getMessage());
}
}
4、总结
监听器默认同步执行,事件的所有监听器是同步执行的,需要评估同步阻塞对当前主流程带来的影响,建议使用异步的方式。
监听器的事件处理并不可靠,因此建议 Spring Event 应仅使用在应用程序内部组件解耦且没有可靠性要求的场景,比如消息通知等。
保持监听器的逻辑尽可能小,事件监听器的逻辑应该保持在最低限度,仅仅是充当程序内部不同部分的粘合剂,任何实质性的逻辑应该放在具体的服务类实现。
谨慎使用条件监听器和事务监听器,虽然两者都是强大的工具,但过多的使用会导致我们的程序出现难以调试的问题。
薔薇猛虎皆成個性,陽光雨露俱是天恩!
浙公网安备 33010602011771号