Spring事件摸摸摸

简介: Spring事件是什么?如何使用才能满足我的需求,这里就来讲解Spring事件的用法和特性。

Spring事件

概述

   Spring事件是Spring Framework中观察者模式的体现,其主要应用于ApplicationContext生命周期中各关键点的通知。

   文档:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/htmlsingle/#context-functionality-events

   文档中有一段特别说明,大概的意思就是从4.2版本开始事件得到了巨大的升级,加入了基于注解的使用方式和用任意对象作为事件,下面都会进行讲解。

As of Spring 4.2, the event infrastructure has been significantly improved and offers an annotation-based model as well as the ability to publish any arbitrary event (that is, an object that does not necessarily extend from ApplicationEvent). When such an object is published, we wrap it in an event for you.


分类

   从文档章节标题来看,事件分为标准事件和自定义事件。标准事件就是Spring内置的事件,下图就是Spring Framework中的标准事件;自定义事件就是用户利用框架事件机制创建的事件。

image.png

原始用法

最早的实现方式是继承和实现对应的接口,主要包括ApplicationEventApplicationEventPublisherAwareApplicationListener

1. 定义事件

事件需要继承ApplicationEvent,事件中包含了你需要传递的数据

publicclassBlockedListEventextendsApplicationEvent {
privatefinalStringaddress;
privatefinalStringcontent;
publicBlockedListEvent(Objectsource, Stringaddress, Stringcontent) {
super(source);
this.address=address;
this.content=content;
    }
// accessor and other methods...}

2. 创建事件监听

监听要实现ApplicationListener接口,实现接收事件方法onApplicationEvent(evetn)

publicclassBlockedListNotifierimplementsApplicationListener<BlockedListEvent> {
privateStringnotificationAddress;
publicvoidsetNotificationAddress(StringnotificationAddress) {
this.notificationAddress=notificationAddress;
    }
publicvoidonApplicationEvent(BlockedListEventevent) {
// 处理收到的事件    }
}

3. 发布事件

发布事件使用框架内的ApplicationEventPublisher实现类的实例。由于ApplicationContext也实现了该接口,所以用ApplicationContext也可以发布事件,代码applicationContext.publishEvent(event)

publicclassEmailServiceimplementsApplicationEventPublisherAware {
privateList<String>blockedList;
privateApplicationEventPublisherpublisher;
publicvoidsetBlockedList(List<String>blockedList) {
this.blockedList=blockedList;
    }
publicvoidsetApplicationEventPublisher(ApplicationEventPublisherpublisher) {
this.publisher=publisher;
    }
publicvoidsendEmail(Stringaddress, Stringcontent) {
if (blockedList.contains(address)) {
publisher.publishEvent(newBlockedListEvent(this, address, content));
return;
        }
// send email...    }
}

4. 总结

这是最原始的使用方式,由于Java是单继承,这样会产生很大的限制,而且继承和实现也会导致框架的侵入性


用注解优化Listener

作为上一种使用方式的升级,注解的加入不但减少了框架的侵入还支持了监听多个事件甚至做到了按条件监听事件

// 基本用法publicclassBlockedListNotifier {
@EventListenerpublicvoidprocessBlockedListEvent(BlockedListEventevent) {
// notify appropriate parties via notificationAddress...    }
}
// 监听多个事件,但注意方法参数@EventListener({ContextStartedEvent.class, ContextRefreshedEvent.class})
publicvoidhandleContextStart() {
// ...}
// 按特定条件接收事件,具体用法见官方文档@EventListener(condition="#blEvent.content == 'my-event'")
publicvoidprocessBlockedListEvent(BlockedListEventblEvent) {
// notify appropriate parties via notificationAddress...}
// 接收事件后发布另一个事件,注意返回值,甚至你可以返回一批事件。另外,文档中特别注明异步事件不支持@EventListenerpublicListUpdateEventhandleBlockedListEvent(BlockedListEventevent) {
// notify appropriate parties via notificationAddress and// then publish a ListUpdateEvent...}
//

异步事件

默认情况下,Listener是同步处理事件的,你可以理解为发布事件的方法同步调用处理事件的方法。但通常情况是希望是异步调用。那么实现方式是使用@Async注解。

@EventListener@AsyncpublicvoidprocessBlockedListEvent(BlockedListEventevent) {
// BlockedListEvent is processed in a separate thread}


最后说明一下,异步事件中,Listener抛出的异常不会传递到发布方。也无法通过返回值来发布新的事件。


循序监听

当有多个监听器监听同一个事件且需要指定监听的顺序时,需要使用@Order指定。

@EventListener@Order(42)
publicvoidprocessBlockedListEvent(BlockedListEventevent) {
// notify appropriate parties via notificationAddress...}


通过泛型限定监听范围

通过对事件增加泛型,可以控制监听器监听的事件范围

@EventListenerpublicvoidonPersonCreated(EntityCreatedEvent<Person>event) {
// ...}

如上,当需要定义一个非固定类型的泛型事件时,可以用下面的方式

publicclassEntityCreatedEvent<T>extendsApplicationEventimplementsResolvableTypeProvider {
publicEntityCreatedEvent(Tentity) {
super(entity);
    }
@OverridepublicResolvableTypegetResolvableType() {
returnResolvableType.forClassWithGenerics(getClass(), ResolvableType.forInstance(getSource()));
    }
}

使用任意类型作为事件

原始用法中说到,作为单继承的语言,事件继承ApplicationEvent会产生很多限制。而Spring框架也在4.2进行了升级,任意的对象都可以作为一个事件发布出去,也就是说事件不必继承ApplicationEvent,普通的Java Bean就可以作为事件。

publicclassBlockedListEvent {
privatefinalStringaddress;
privatefinalStringcontent;
publicBlockedListEvent(Stringaddress, Stringcontent) {
this.address=address;
this.content=content;
    }
// accessor and other methods...}

ApplicationEventPublisher也有对应的发布方法

image.png











目录
相关文章
|
12天前
|
存储 安全 Java
事件的力量:探索Spring框架中的事件处理机制
事件的力量:探索Spring框架中的事件处理机制
26 0
|
3月前
|
XML Java 数据格式
聊聊Spring事件及其应用
在 JDK 中已经提供相应的自定义事件发布功能的基础类: - `java.util.EventObject`类 :自定义**事件**类型 - `java.util.EventListener`接口:事件的**监听器**
27 1
聊聊Spring事件及其应用
|
1月前
|
Java Spring
除了spring自带的事件,你还可以这样使用事件
除了spring自带的事件,你还可以这样使用事件
14 3
|
1月前
|
存储 安全 Java
全面探索Spring框架中的事件处理机制
在现代应用程序中,各个组件之间的通信是至关重要的。想象一下,你的应用程序中的各个模块像是一个巨大的交响乐团,每个模块都是一位音乐家,而Spring事件机制就像是指挥家,将所有音乐家协调得天衣无缝。这种松耦合的通信方式使你的应用程序更加灵活、可维护,而且能够轻松应对变化。现在,让我们进入这个令人兴奋的音乐厅,探索Spring事件的世界。
|
2月前
|
NoSQL Java Redis
Spring boot 实现监听 Redis key 失效事件
【2月更文挑战第2天】 Spring boot 实现监听 Redis key 失效事件
69 0
|
10月前
|
Java Spring 容器
spring使用容器发布事件
spring使用容器发布事件
|
10月前
|
Java Spring
spring如何保证事件顺序发送
spring如何保证事件顺序发送
|
10月前
|
Java Spring
spring如何避免重复事件触发
spring如何避免重复事件触发
|
10月前
|
Java Spring
|
10月前
|
监控 Java Spring
spring通过监听事件记录系统日志
spring通过监听事件记录系统日志

热门文章

最新文章