一、前言

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

二、具体实现步骤

  1. 首先定义一个事件类Event

    public class NoticeEvent extends ApplicationEvent {
        private String message;
    
        public NoticeEvent(String message) {
            super(message);
            this.message = message;
        }
    
        public String getMessage() {
            return message;
        }
    }
    

    所有事件类都需要继承ApplicationEvent

  2. 创建事件监听类
    @Component
    public class NoticeListener implements ApplicationListener<NoticeEvent> {
    
        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容器中。

  3. 发布事件

    @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

image-20250928210455207.png

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

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

image-20250928211058840.png

然后测试:

image-20250928211641359.png

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

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

@Configuration
@EnableAsync
public 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;
    }
}

测试:

image-20250928212329007.png

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

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

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]