Springboot 事件通知监听
一、同步发送
在 Spring Boot 中,事件监听机制是一种非常有用的设计模式,它允许组件之间进行解耦通信,一个组件发布事件,其他组件可以监听这些事件并做出相应的处理。下面详细介绍其底层原理和用例。
底层原理
1. 事件驱动模型基础
Spring Boot 的事件监听机制基于经典的事件驱动模型,该模型包含三个核心角色:事件(Event)、事件发布者(Publisher)和事件监听器(Listener)。
- 事件(Event):是一个对象,用于封装事件的相关信息,通常继承自
ApplicationEvent
类。 - 事件发布者(Publisher):负责创建并发布事件,一般通过
ApplicationEventPublisher
接口来发布事件。 - 事件监听器(Listener):监听特定类型的事件,当事件被发布时,监听器会执行相应的处理逻辑,通常实现
ApplicationListener
接口或者使用@EventListener
注解。
2. Spring 的事件体系
Spring 有自己的一套事件体系,ApplicationEvent
是所有事件的基类,ApplicationListener
是所有监听器的基类。Spring Boot 在此基础上进行了扩展,提供了一些内置的事件,如 ApplicationStartedEvent
、ApplicationReadyEvent
等。
3. 事件发布与监听流程
- 事件发布:当某个组件需要发布事件时,会调用
ApplicationEventPublisher
的publishEvent
方法,将事件对象传递给该方法。 - 事件传播:
ApplicationEventPublisher
会将事件广播给所有注册的监听器。 - 事件监听:监听器会根据事件的类型进行匹配,如果匹配成功,则执行相应的处理逻辑。
用例说明
1. 自定义事件
首先,创建一个自定义事件类,继承自 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;
}
}
2. 事件发布者
创建一个事件发布者类,通过 ApplicationEventPublisher
发布事件:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
// 事件发布者类
@Component
public class CustomEventPublisher {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void publishCustomEvent(String message) {
CustomEvent customEvent = new CustomEvent(this, message);
eventPublisher.publishEvent(customEvent);
}
}
3. 事件监听器
有两种方式可以创建事件监听器:
方式一:实现 ApplicationListener
接口
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
// 事件监听器类,实现 ApplicationListener 接口
@Component
public class CustomEventListener implements ApplicationListener<CustomEvent> {
@Override
public void onApplicationEvent(CustomEvent event) {
System.out.println("Received custom event: " + event.getMessage());
}
}
方式二:使用 @EventListener
注解
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
// 事件监听器类,使用 @EventListener 注解
@Component
public class AnotherCustomEventListener {
@EventListener
public void handleCustomEvent(CustomEvent event) {
System.out.println("Another listener received custom event: " + event.getMessage());
}
}
4. 测试事件监听
创建一个测试类,调用事件发布者发布事件:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class EventListenerExampleApplication implements CommandLineRunner {
@Autowired
private CustomEventPublisher eventPublisher;
public static void main(String[] args) {
SpringApplication.run(EventListenerExampleApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
eventPublisher.publishCustomEvent("This is a custom event message.");
}
}
代码解释
- 自定义事件
CustomEvent
:封装了事件的相关信息,继承自ApplicationEvent
。 - 事件发布者
CustomEventPublisher
:通过ApplicationEventPublisher
发布自定义事件。 - 事件监听器
CustomEventListener
和AnotherCustomEventListener
:分别使用实现ApplicationListener
接口和@EventListener
注解的方式监听自定义事件,并在事件发生时执行相应的处理逻辑。 - 测试类
EventListenerExampleApplication
:在应用启动后,调用事件发布者发布事件,触发监听器的处理逻辑。
通过以上步骤,你可以在 Spring Boot 中实现自定义事件的发布和监听,利用事件监听机制实现组件之间的解耦通信。
二、多事件发布器+自定义多线程
1 - 配置
配置多事件发布器+异步多线程处理多事件发布
重点说明:多事件发布器 Config 配置类中,@Bean(name = "applicationEventMulticaster") 必须要明确指明 Bean name属性为 applicationEventMulticaster ,根据springboot约定大于配置,applicationEventMulticaster 是个专用名字,springboot启动后,会自动加载此 多事件发布器,否则自定义的多事件发布器不生效,从测试用例的线程名字能够观察出。
package com.example.MySpringBootTest.eventmutilcaser;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import java.util.concurrent.Executor;
@Configuration
public class AsyncEventConfig {
@Bean
public Executor asyncExecutor() {
SimpleAsyncTaskExecutor simpleAsyncTaskExecutor = new SimpleAsyncTaskExecutor();
simpleAsyncTaskExecutor.setThreadNamePrefix("weiwei-mutil-event-");
return simpleAsyncTaskExecutor;
}
@Bean(name = "applicationEventMulticaster")
public ApplicationEventMulticaster simpleApplicationEventMulticaster() {
SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster();
simpleApplicationEventMulticaster.setTaskExecutor(asyncExecutor());
return simpleApplicationEventMulticaster;
}
}
2 - 定义业务事件
package com.example.MySpringBootTest.eventmutilcaser;
import org.springframework.context.ApplicationEvent;
public class FirstEvent extends ApplicationEvent {
private String message;
public FirstEvent(Object source, String message) {
super(source);
this.message=message;
}
public String getMessage() {
return message;
}
}
package com.example.MySpringBootTest.eventmutilcaser;
import org.springframework.context.ApplicationEvent;
public class SecondEvent extends ApplicationEvent {
private String message;
public SecondEvent(Object source, String message) {
super(source);
this.message = message;
}
public String getMessage() {
return message;
}
}
3 - 定义事件发布者
package com.example.MySpringBootTest.eventmutilcaser;
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 publishFirstEvent(String message) {
FirstEvent firstEvent = new FirstEvent(this, message);
eventPublisher.publishEvent(firstEvent);
}
public void publishSecondEvent(String data) {
SecondEvent secondEvent = new SecondEvent(this, data);
eventPublisher.publishEvent(secondEvent);
}
}
4 - 定义事件监听者
package com.example.MySpringBootTest.eventmutilcaser;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class AsyncEventListener {
@EventListener
public void handleFirstEvent(FirstEvent event) {
System.out.println(Thread.currentThread().getName() + " received first event: " + event.getMessage());
}
@EventListener
public void handleSecondEvent(SecondEvent event) {
System.out.println(Thread.currentThread().getName() + " received second event: " + event.getMessage());
}
}
5 - 测试用例及输出
@Autowired
EventPublisher eventPublisher;
@RequestMapping("/mutilEventTest")
public void mutilEventTest() {
System.out.println("start mutilEventTest");
eventPublisher.publishFirstEvent("the first message.");
eventPublisher.publishSecondEvent("the second data.");
System.out.println("end mutilEventTest");
}
// Before executing controller method: mutilEventTest
// start mutilEventTest
// weiwei-mutil-event-25 received first event: the first message.
// weiwei-mutil-event-27 received second event: the second data.
// end mutilEventTest
// After executing controller method: mutilEventTest