Spring5参考指南:事件Event

简介: Spring5参考指南:事件Event

文章目录



Spring提供了很方便的事件的处理机制,包括事件类ApplicationEvent和事件监听类ApplicationListener。 他实现的是设计者模式,如果实现了ApplicationListener接口的bean部署到Spring容器中,则每次ApplicationEvent发布到ApplicationContext时,都会通知该bean。


从Spring4.2开始,提供了基于注解的事件,即事件对象不一定要从ApplicationEvent来扩展。Spring会自动将其封装成一个事件对象。


下面是Spring的标准事件描述:


Event 解释
ContextRefreshedEvent 在初始化或刷新ApplicationContext时发布(例如,通过在ConfigurableApplicationContext接口上使用refresh()方法)。这里,“初始化”意味着加载所有bean,检测并激活后处理器bean,预先实例化单例,并且ApplicationContext对象准备好使用。只要上下文未关闭,只要所选的ApplicationContext实际上支持此类“热”刷新,就可以多次触发刷新。例如,XMLWebApplicationContext支持热刷新,但GenericApplicationContext不支持。
ContextStartedEvent 在可配置的ApplicationContext接口上使用start()方法启动ApplicationContext时发布。这里,“启动”意味着所有生命周期bean都会收到一个显式的启动信号。通常,此信号用于在显式停止后重新启动bean,但也可以用于启动尚未配置为自动启动的组件(例如,初始化时尚未启动的组件)。
ContextStoppedEvent 在可配置的ApplicationContext接口上使用stop()方法停止ApplicationContext时发布。这里,“停止”意味着所有生命周期bean都会收到一个明确的停止信号。停止的上下文可以通过start()调用重新启动。
ContextClosedEvent 在可配置的ApplicationContext接口上使用close()方法关闭ApplicationContext时发布。这里,“关闭”意味着所有的单例beans都被销毁了。封闭的环境达到了生命的尽头。无法刷新或重新启动。
RequestHandledEvent 一个特定于Web的事件,告诉所有bean HTTP请求已被服务。此事件在请求完成后发布。此事件仅适用于使用Spring的DispatcherServlet的Web应用程序。


基于继承的Event


你也可以自定义事件,下面是一个继承ApplicationEvent的例子:


public class BlackListEvent extends ApplicationEvent {
    private final String address;
    private final String content;
    public BlackListEvent(Object source, String address, String content) {
        super(source);
        this.address = address;
        this.content = content;
    }
}


若要发布自定义ApplicationEvent,在ApplicationEventPublisher上调用PublishEvent

()方法。通常可以通过实现ApplicationEventPublisherAware接口来实现,如下所示:


public class EmailService implements ApplicationEventPublisherAware {
    private List<String> blackList;
    private ApplicationEventPublisher publisher;
    public void setBlackList(List<String> blackList) {
        this.blackList = blackList;
    }
    public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }
    public void sendEmail(String address, String content) {
        if (blackList.contains(address)) {
            publisher.publishEvent(new BlackListEvent(this, address, content));
            return;
        }
    }
}


在配置时,Spring容器检测到EmailService实现了ApplicationEventPublisherAware,并自动调用setApplicationEventPublisher()。实际上,传入的参数是Spring容器本身。


您正在通过其applicationEventPublisher接口与应用程序上下文进行交互。


要接收定制的applicationEvent,可以创建一个实现applicationListener的类,并将其注册为SpringBean。下面的示例显示了这样的类:


public class BlackListNotifier implements ApplicationListener<BlackListEvent> {
    private String notificationAddress;
    public void setNotificationAddress(String notificationAddress) {
        this.notificationAddress = notificationAddress;
    }
    public void onApplicationEvent(BlackListEvent event) {
        // notify appropriate parties via notificationAddress...
    }
}


这里使用了ApplicationListener 的BlackListEvent泛型。意味着onApplicationEvent()方法可以保持类型安全,避免任何向下强制转换的需要。


但请注意,默认情况下,事件侦听器同步接收事件。这意味着publishEvent()方法将一直阻塞,直到所有侦听器完成对事件的处理。


下面是注册和配置bean的例子:


<bean id="emailService" class="example.EmailService">
    <property name="blackList">
        <list>
            <value>known.spammer@example.org</value>
            <value>known.hacker@example.org</value>
            <value>john.doe@example.org</value>
        </list>
    </property>
</bean>
<bean id="blackListNotifier" class="example.BlackListNotifier">
    <property name="notificationAddress" value="blacklist@example.org"/>
</bean>


Spring的事件机制是为同一应用程序上下文中SpringBean之间的简单通信而设计的。对于更复杂的企业集成需求,可以使用Spring Integration的AMQP模型来处理。


基于注解的Event


从Spring4.2开始,您可以使用EventListener注解在托管bean的任何公共方法上注册事件侦听器。BlackListNotifier程序可以改写如下:


public class BlackListNotifierAnnotation {
    private String notificationAddress;
    public void setNotificationAddress(String notificationAddress) {
        this.notificationAddress = notificationAddress;
    }
    @EventListener
    public void processBlackListEvent(BlackListEvent event) {
        // notify appropriate parties via notificationAddress...
    }
}


如果您的方法应该监听多个事件,或者您想要定义它而不使用任何参数,那么也可以在注解本身上指定事件类型。以下示例显示了如何执行此操作:


@EventListener({ContextStartedEvent.class, ContextRefreshedEvent.class})
    public void handleContextStart() {
    }


还可以使用定义spEL表达式的注解的条件属性添加其他运行时筛选,该表达式应与实际调用特定事件的方法相匹配。


下面的例子显示了如何重写通知程序,以便仅在事件的内容属性等于my-event时调用:


@EventListener(condition = "#blEvent.content == 'my-event'")
    public void processBlackListSPELEvent(BlackListEvent blEvent) {
        // notify appropriate parties via notificationAddress...
    }


下表列出了上下文可用的项,以便您可以将它们用于条件事件处理:


name Location 描述 例子
Event root object 真实的ApplicationEvent #root.event
Arguments array root object 调用目标的参数 #root.args[0]
Argument name evaluation context 任何方法参数的名称。如果由于某种原因,名称不可用(例如,因为没有调试信息),参数名称也可以在 #a<#arg>下使用,其中#arg表示参数索引(从0开始)。 #blEvent or #a0 (也可以使用 #p0 or #p<#arg>)


异步侦听器


如果希望特定的侦听器异步处理事件,可以重用常规的@Async支持。下面是@Async的例子:


@Async
    @EventListener
    public void processBlackListEvent(BlackListEvent event) {
        // notify appropriate parties via notificationAddress...
    }


Listeners排序


如果需要先调用一个监听器,然后再调用另一个监听器,则可以将@order注解添加到方法声明中,如下所示:


@EventListener
    @Order(12)
    public void processBlackListEvent(BlackListEvent event) {
        // notify appropriate parties via notificationAddress...
    }
相关文章
|
6月前
|
存储 安全 Java
事件的力量:探索Spring框架中的事件处理机制
事件的力量:探索Spring框架中的事件处理机制
74 0
|
6月前
|
XML Java 数据格式
聊聊Spring事件及其应用
在 JDK 中已经提供相应的自定义事件发布功能的基础类: - `java.util.EventObject`类 :自定义**事件**类型 - `java.util.EventListener`接口:事件的**监听器**
64 1
聊聊Spring事件及其应用
|
2月前
|
监控 Java C#
Spring Event 的介绍
Spring Event 是 Spring 框架中的事件驱动机制,允许组件间进行同步或异步消息传递,无需直接依赖。它包括事件(Event)、事件发布者(Publisher)和事件监听器(Listener),通过 `ApplicationEventPublisher` 广播事件,实现松耦合通信,增强模块化和可维护性。Spring 还提供了多种内置事件,如 `ContextRefreshedEvent` 和 `ContextClosedEvent`,支持同步及异步处理,并具备良好的扩展性。
|
3月前
|
Java Spring 供应链
Spring 框架事件发布与监听机制,如魔法风暴席卷软件世界,开启奇幻编程之旅!
【8月更文挑战第31天】《Spring框架中的事件发布与监听机制》介绍了Spring中如何利用事件发布与监听机制实现组件间的高效协作。这一机制像城市中的广播系统,事件发布者发送消息,监听器接收并响应。通过简单的示例代码,文章详细讲解了如何定义事件类、创建事件发布者与监听器,并确保组件间松散耦合,提升系统的可维护性和扩展性。掌握这一机制,如同拥有一把开启高效软件开发大门的钥匙。
49 0
|
6月前
|
NoSQL Java Redis
Spring Boot 监听 Redis Key 失效事件实现定时任务
Spring Boot 监听 Redis Key 失效事件实现定时任务
141 0
|
3月前
|
消息中间件 Java 开发工具
【Azure 事件中心】Spring Cloud Stream Event Hubs Binder 发送Event Hub消息遇见 Spec. Rule 1.3 - onSubscribe, onNext, onError and onComplete signaled to a Subscriber MUST be signaled serially 异常
【Azure 事件中心】Spring Cloud Stream Event Hubs Binder 发送Event Hub消息遇见 Spec. Rule 1.3 - onSubscribe, onNext, onError and onComplete signaled to a Subscriber MUST be signaled serially 异常
|
3月前
|
Java Spring
【Azure 事件中心】Spring Boot 集成 Event Hub(azure-spring-cloud-stream-binder-eventhubs)指定Partition Key有异常消息
【Azure 事件中心】Spring Boot 集成 Event Hub(azure-spring-cloud-stream-binder-eventhubs)指定Partition Key有异常消息
|
4月前
|
存储 设计模式 Java
Spring Boot中的事件溯源模式
Spring Boot中的事件溯源模式
|
5月前
|
设计模式 Java Spring
Spring Boot中的事件通知机制
Spring Boot中的事件通知机制
|
6月前
|
Java Spring
除了spring自带的事件,你还可以这样使用事件
除了spring自带的事件,你还可以这样使用事件
41 3