在Spring Boot单体项目中,你可以使用Spring Event来处理应用程序中的事件。Spring Event是Spring框架中的一个重要组件,它允许你在应用程序中发布和监听事件,实现解耦和异步处理。
下面是在Spring Boot项目中如何使用Spring Event的简单示例: (可应用于大多数场景下的异步解耦开发)
通用配置
- 首先创建异步处理事件
AsyncEvent,继承ApplicationEvent类:
import org.springframework.context.ApplicationEvent;
// 异步处理事件
public abstract class AsyncEvent extends ApplicationEvent {
public AsyncEvent(Object source) {
super(source);
}
}
- 创建事件处理线程配置
EventConfig类:
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import javax.annotation.Nullable;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.ResolvableType;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
* 事件处理线程配置
*/
@Configuration
public class EventConfig {
@Bean(AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME)
public SimpleApplicationEventMulticaster myEventMulticaster() {
MyApplicationEventMulticaster myApplicationEventMulticaster = new MyApplicationEventMulticaster();
myApplicationEventMulticaster.setTaskExecutor(taskExecutor());
return myApplicationEventMulticaster;
}
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 核心线程数
executor.setCorePoolSize(5);
// 最大线程数
executor.setMaxPoolSize(20);
// 队列容量
executor.setQueueCapacity(100);
// 线程活跃时间(秒)
executor.setKeepAliveSeconds(300);
// 线程名前缀
executor.setThreadNamePrefix("Async_event_executor-");
// 拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
// 关闭线程时是否等待
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
static class MyApplicationEventMulticaster extends SimpleApplicationEventMulticaster {
@Override
public void multicastEvent(@NotNull final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = eventType != null ? eventType : resolveDefaultEventType(event);
Executor executor = this.getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
// 配置了任务管理器 和 事件为异步处理事件,则调用任务处理器异步处理
if (executor != null && event instanceof AsyncEvent) {
executor.execute(() -> this.invokeListener(listener, event));
} else {
this.invokeListener(listener, event);
}
}
}
private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
return ResolvableType.forInstance(event);
}
}
}
事件处理
- 创建异步事件(可根据业务自行定义)- 无参
public class TestEvent extends AsyncEvent {
public TestEvent(Object source) {
super(source);
}
}
有参示例:
public class TestEvent extends AsyncEvent {
private String name;
// ..... 可继续添加多个
public TestEvent(Object source) {
super(source);
}
public TestEvent(Object source, String name, ......) {
super(source);
this.name = name;
// ......
}
public String getName() {
return name;
}
// ...get
}
- 事件发布
@RequestMapping("/v1")
@RestController
public class EventController {
@Resource
private ApplicationEventPublisher publisher;
@GetMapping("/publish-event")
public String publishEvent(@RequestParam String name) {
// 无参事件发布
publisher.publishEvent(new TestEvent(this));
// 需要带参就用这种方式
// publisher.publishEvent(new TestEvent(this, name));
return "发布事件成功";
}
}
- 事件监听处理,使用
@EventListener注解搞定
service
/**
* @param: event 事件参数
*/
@EventListener // 此注解也可直接写在serviceImpl
void listenerEvent(TestEvent event);
serviceImpl
@Override
public void listenerEvent(TestEvent event) {
System.out.println("事件接收成功");
// 业务处理.....
// 如果有参数可通过get获取
// ......
System.out.println("事件处理完成");
}
注意:每个事件只需要定义一个,只需publishEvent发布一次,只要使用@EventListener注解的方法都会接收到对应的事件。(发布-订阅模式)