Spring @EventListener 注解

@EventListener是 Spring 框架提供的一个注解,用于在应用程序中注册事件监听器。它允许你在 Spring 管理的 Bean 中轻松地监听 Spring 的应用程序事件,并在事件发生时执行相应的处理逻辑。

@EventListener 是 Spring 框架提供的一个注解,用于在应用程序中注册事件监听器。它允许你在 Spring 管理的 Bean 中轻松地监听 Spring 的应用程序事件,并在事件发生时执行相应的处理逻辑。

Spring 的事件机制是一种松耦合的通信方式,它允许不同组件之间通过事件的发布和监听进行交互,而无需直接依赖彼此。这样可以提高系统的可维护性和可扩展性。

基本方法

创建事件类

首先,需要定义一个事件类,这个类通常继承自ApplicationEvent。例如:

import org.springframework.context.ApplicationEvent;

public class CustomEvent extends ApplicationEvent {
    private String message;

    public CustomEvent(Object source, String message) {
        super(source);
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

发布事件

使用 ApplicationEventPublisher 来发布事件。可以通过在 Spring 的 Bean 中注入ApplicationEventPublisher,并调用其 publishEvent 方法来实现。例如:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

@Component
public class EventPublisher {
    @Autowired
    private ApplicationEventPublisher eventPublisher;

    public void publishCustomEvent(String message) {
        CustomEvent customEvent = new CustomEvent(this, message);
        eventPublisher.publishEvent(customEvent);
    }
}

监听事件

在另一个 Spring Bean 中,使用@EventListener注解来监听CustomEvent。例如:

import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class EventListenerBean {
    @EventListener
    public void handleCustomEvent(CustomEvent customEvent) {
        System.out.println("Received Custom Event: " + customEvent.getMessage());
    }
}

工作原理

当使用 @EventListener 注解标记一个方法时,Spring 会在容器启动时扫描并注册该方法作为一个事件监听器。这个方法会被添加到一个内部的监听器列表中。

当 ApplicationEventPublisher 发布一个事件时,Spring 会遍历其内部的监听器列表,找到与该事件类型匹配的监听器方法(即方法参数类型匹配事件类型)。

对于 CustomEvent,当 EventPublisher 发布该事件时,Spring 会调用 EventListenerBean 中带有 @EventListener 注解且参数为 CustomEvent 的方法,执行相应的处理逻辑。

事件处理方法的参数

单一事件参数:通常,处理方法的参数是要监听的事件类型,如上述的 handleCustomEvent(CustomEvent customEvent),参数为 CustomEvent。

使用条件表达式:可以使用 condition 属性对事件进行筛选,只在满足条件时执行处理逻辑。例如:

@EventListener(condition = "#event.message.startsWith('Hello')")
public void handleEventWithCondition(CustomEvent event) {
    System.out.println("Received event with message starting with Hello: " + event.getMessage());
}

这里的 condition 属性使用了 Spring 表达式语言(SpEL),只有当事件消息以 Hello 开头时,该处理方法才会被调用。

使用异步处理

可以将@EventListener注解与@Async注解结合使用,使事件处理方法在一个单独的线程中异步执行。例如:

import org.springframework.scheduling.annotation.Async;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class AsyncEventListenerBean {
    @Async
    @EventListener
    public void handleCustomEventAsync(CustomEvent customEvent) {
        System.out.println("Received Custom Event Asynchronously: " + customEvent.getMessage());
    }
}

这样,事件处理逻辑将在一个单独的线程池中异步执行,不会阻塞主线程,适用于处理耗时较长的事件处理任务。

事件的继承和多态性

如果一个事件监听器监听的是一个父类事件,它也会收到子类事件。例如,如果有一个 BaseEvent 类和一个 ChildEvent 类继承自 BaseEvent,并且有一个监听器监听 BaseEvent:

import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class BaseEventListener {
    @EventListener
    public void handleBaseEvent(BaseEvent baseEvent) {
        System.out.println("Received Base Event: " + baseEvent.getClass());
    }
}

当发布 ChildEven t时,该监听器也会被触发,因为 ChildEvent 是 BaseEvent 的子类。

在 Spring Boot 中的应用

在 Spring Boot 应用中,@EventListener 可以用于各种场景,例如监听应用程序的启动事件 ApplicationStartedEvent 或 ApplicationReadyEvent,以在应用程序启动或准备好后执行一些初始化或后续操作。例如:

import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class ApplicationStartListener {
    @EventListener
    public void onApplicationStarted(ApplicationStartedEvent event) {
        System.out.println("Application has started.");
    }
}

也可以监听与配置文件加载、环境变更等相关的事件,根据不同的事件执行相应的逻辑,帮助实现更灵活的应用程序启动流程和状态管理。
使用@EventListener可以帮助你在 Spring 应用中实现松耦合的事件驱动架构,提高系统的可维护性和可扩展性,同时也为不同组件之间的通信和协作提供了一种简洁有效的方式。

 

谁不会休息,谁就不会工作。 —— 列宁
0 不喜欢
说说我的看法 -
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号