聊聊Spring事件机制

B站影视 港台电影 2025-09-29 13:33 1

摘要:在我们平时的开发工作当中,肯定有这样一些业务场景,这块业务完成后,就给用户推送一些消息以提醒用户,比如给用户发送一条下单成功信息,对于这种非核心的业务功能其实我们可以单独拿出来,创建一个事件去异步执行,这样子就可以实现核心业务和子业务的解耦。

在我们平时的开发工作当中,肯定有这样一些业务场景,这块业务完成后,就给用户推送一些消息以提醒用户,比如给用户发送一条下单成功信息,对于这种非核心的业务功能其实我们可以单独拿出来,创建一个事件去异步执行,这样子就可以实现核心业务和子业务的解耦。

首先定义一个事件类Eventpublic class NoticeEvent extends ApplicationEvent { private String message;public NoticeEvent(String message) { super(message); this.message = message; }public String getMessage { return message; } } #技术分享

所有事件类都需要继承 ApplicationEvent 。

创建事件监听类 @Componentpublic class NoticeListener implements ApplicationListener {private static final Logger logger = LoggerFactory.getLogger(NoticeListener.class);@Override public void onApplicationEvent(NoticeEvent event) { try { logger.info("接收到的消息:{}",event); Thread.sleep(5000); logger.info("处理消息完成:{}",event); }catch (Exception e){ e.printStackTrace; } } }

该类用于监听指定事件的类,需要实现 ApplicationListener 接口。注意这里需要加上 @Component 注解,将其注入 Spring 容器中。

发布事件@RestController@RequestMapping("/event")public class EventController { private static final Logger logger = LoggerFactory.getLogger(EventController.class); @Autowired private ApplicationEventPublisher publisher;@GetMapping("/notice/{message}") public void notice(@PathVariable(name = "message")String message) { logger.info("开始发送消息:{}",message); publisher.publishEvent(new NoticeEvent(message)); logger.info("消息发送完成"); } }

使用 Spring 提供的 ApplicationEventPublisher 来发布自定义事件。

代码写完了,我们直接来测试看效果:

启动服务,访问接口:http://localhost:8003/batch/event/notice/testMessage

我们可以看到,从始至终都是同一条线程去完成这个任务的,并没有异步去执行。

从这里我们可以得知,默认是没有开启异步的,我们需要手动配置开启异步功能,我们需要在启动类中加上 @EnableAsync 注解,该注解用于声明启用 Spring 的异步方法执行功能。然后我们在监听方法上加上 @Async 注解,说明当前方法使用异步去执行。

然后测试:

从截图可以看出,已经实现了异步功能,主线程为 http-nio-8003-exec-1,监听线程为 task-1。从日志打印可以看出,接口直接返回了,并没有等监听线程执行完后才返回。

这里我们再提一点,开启异步后,会使用 Spring 内部默认的线程池,我们可以自定义这个线程池,如下:

@Configuration@EnableAsyncpublic class AsyncConfig implements AsyncConfigurer {private final Logger log = LoggerFactory.getLogger(this.getClass);@Override public Executor getAsyncExecutor { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor; taskExecutor.setCorePoolSize(2); taskExecutor.setMaxPoolSize(10); taskExecutor.setQueueCapacity(15); taskExecutor.setThreadNamePrefix("async-thread-"); taskExecutor.initialize; return taskExecutor; } }

测试:

已经使用上我们自定义的线程池了。

好了,关于 Spring 中的 ApplicationEvent 和 ApplicationListener 我们就介绍这么多。

来源:墨码行者

相关推荐