Spring 的订阅与发布事件功能是非常有用的。要使用Spring的订阅与发布事件功能,需要以下步骤:
- 在Spring 4.2版本之前,自定义的
Event
需要继承ApplicationEvent
;在Spring 4.2版本开始,自定义的Event
不再需要继承ApplicationEvent
。 - 事件发布者需要注入
ApplicationEventPublisher
- 事件监听者需要实现
ApplicationListener
接口
发布与监听事件
自定义事件
public class MyEvent extends ApplicationEvent {
private String message;
public MyEvent(Object source, String message) {
super(source);
this.message = message;
}
public String getMessage() {
return message;
}
}
定义事件发布者
@Component
public class MyPublisher {
@Autowired
private ApplicationEventPublisher publisher;
public void publishEvent(String message) {
publisher.publishEvent(new MyEvent(this, message));
}
}
从Spring 4.2开始,ApplicationEventPublisher
接口提供一个方法 publishEvent(Object Event)
,参数是Object对象。这就意味着 Spring的事件不再需要扩展 Application
类。
定义监听者
@Component
public class MyListener implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
System.out.println("处理事件: " + event.getMessage());
}
}
单元测试
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
class MyPublisherTest {
@Autowired
private MyPublisher publisher;
@Test
void publishEvent() {
publisher.publishEvent("Spring 的监听事件");
}
}
异步执行
spring boot 的事件监听默认是同步执行的。这就意味着发布者的线程将会阻塞,直到监听器执行完成。如果开启事件监听器异步执行,我们创建 ApplicationEventMulticaster
对象,并给它添加一个 executor
,最后注册到容器中。
@Configuration
public class AsynchronousSpringEventsConfig {
@Bean(name = "applicationEventMulticaster")
public ApplicationEventMulticaster simpleApplicationEventMulticaster() {
SimpleApplicationEventMulticaster eventMulticaster =
new SimpleApplicationEventMulticaster();
eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());
return eventMulticaster;
}
}
使用注解监听事件
从Spring4.2开始,事件监听器不再需要实现 ApplicationListener
接口,只需要添加注解 @EventListener
在 public
方法上即可。
@Component
public class MySecondListener {
@EventListener
public void handlerEvent(MyEvent event) {
System.out.println("使用注解处理事件:" + event.getMessage());
}
}
@EventListener
有个 condition
属性,我们可以用来指定过滤特定的事件。当 condition
属性执行结果为true时,事件监听才会执行。condition
使用EL表达式。
@Component
public class MySecondListener {
@EventListener(condition = "#myEvent.message.length() > 1")
public void handlerEvent(MyEvent myEvent) {
System.out.println("使用注解处理事件:" + myEvent.getMessage() );
}
}
当事件 MyEvent
的message属性的长度大于1时,执行。
使用注解开启异步
Spring 的异步监听器可以通过注解 @Async
来开启异步执行。除了增加 注解 @Async
以外,我们还需要在 @Configuration
的配置类或 @SpringBootApplication
的类上加上注解 @EnableAsync
,用来激活 @Async
注解。
@Component
public class MySecondListener {
@Async
@EventListener
public void handlerEvent(MySecondEvent myEvent) {
System.out.println("使用注解处理事件:" + myEvent.getMessage() );
}
}
想要了解更多关于 @EventListener
的信息可以参考一下:
泛型的事件监听
Spring支持带有泛型的事件,这样可以更加灵活发布任意对象的事件。
定义带有泛型的事件
public class GenericEvent<T> implements ResolvableTypeProvider{
private T msg;
private boolean success;
public GenericEvent(T msg, boolean success) {
this.msg = msg;
this.success = success;
}
@Override
public ResolvableType getResolvableType() {
return ResolvableType.forClassWithGenerics(getClass(), ResolvableType.forInstance(msg));
}
// getter and setter
}
事件监听器
@Component
public class GenericEventListener {
@EventListener(condition = "#event.success")
public void handlerGenericEvent(GenericEvent<String> event) {
System.out.println("处理带有泛型的事件: " + event.getMsg());
}
}
事务事件监听器
从Spring4.2开始,提供一个新的注解 @TransactionalEventListener
,这个注解是用来监听事务的状态。这里事务的状态4个:
AFTER_COMMIT
:如果事务已经成功完成,将会触发该事件。AFTER_ROLLBACK
:如果事务回滚,将会触发该事件。AFTER_COMPLETION
:如果事务完成,将会触发该事件(包括 AFTER_COMMIT 和 AFTER_ROLLBACK)