Spring注解驱动之ApplicationListener异步处理事件详解

概述

之前我们讲过简单使用ApplicationListener发布事件,处理事件,但是发现是同一个线程发送事件并自己处理事件的。
下面我们就来说下如何使用自定义的线程池来异步处理接收的事件。

示例

实现一个ApplicationListener用于处理事件

package com.atguigu.ext;

import org.springframework.context.ApplicationListener;
import org.springframework.context.PayloadApplicationEvent;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationListener implements ApplicationListener<PayloadApplicationEvent> {

    public void onApplicationEvent(PayloadApplicationEvent applicationEvent) {
        System.out.println("exe thread start:" + Thread.currentThread().getName() + ", time:" + System.currentTimeMillis());
        System.out.println("收到事件:" + applicationEvent);
        System.out.println(applicationEvent.getPayload());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("exe thread end:" + Thread.currentThread().getName() + ", time:" + System.currentTimeMillis());
    }
}

自定义事件多波器

之前看源码可以发现,在容器创建的refresh方法中的initApplicationEventMulticaster()方法执行时,先从容器中获取name为applicationEventMulticaster的组件,如果获取不到就好创建一个默认的applicationEventMulticaster组件,该组件默认是不会设置taskExecutor任务执行器的,所以这里我们自定义一个设置了TaskExecutor的多波器,当执行initApplicationEventMulticaster方法从beanFactory中获取applicationEventMulticaster组件时,走getBean逻辑。BeanFactory.getBean()逻辑是先从容器查看是否有该组件,如果没有获取该组件的定义,如果有定义就会创建一个组件返回并把组件保存到容器中。

package com.atguigu.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.SimpleApplicationEventMulticaster;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Configuration
@ComponentScan("com.atguigu.ext")
public class ExtConfig {

    @Bean
    public SimpleApplicationEventMulticaster applicationEventMulticaster() {
        SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster();
        BlockingQueue<Runnable> blockingQueue = new LinkedBlockingDeque<>(1000);
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 5, 10, TimeUnit.SECONDS, blockingQueue);
        simpleApplicationEventMulticaster.setTaskExecutor(threadPoolExecutor);
        return simpleApplicationEventMulticaster;
    }
}

测试用例

package com.atguigu;

import com.atguigu.config.ExtConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @Description :
 * @Version : V1.0.0
 * @Date : 2022/9/1 15:07
 */
public class AnnotationTest {
    public static void main(String[] args) {
        final AnnotationConfigApplicationContext applicationContext
                = new AnnotationConfigApplicationContext(ExtConfig.class);
        System.out.println("main thread start:" + Thread.currentThread().getName() + ", time:" + System.currentTimeMillis());
        applicationContext.publishEvent("发送事件");
        System.out.println("main thread end:" + Thread.currentThread().getName() + ", time:" + System.currentTimeMillis());
        applicationContext.close();
    }
}

测试结果

main thread start:main, time:1663499481185
main thread end:main, time:1663499481188
exe thread start:pool-1-thread-1, time:1663499481188
收到事件:org.springframework.context.PayloadApplicationEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@5ebec15: startup date [Sun Sep 18 19:11:20 CST 2022]; root of context hierarchy]
发送事件
九月 18, 2022 7:11:21 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@5ebec15: startup date [Sun Sep 18 19:11:20 CST 2022]; root of context hierarchy
exe thread end:pool-1-thread-1, time:1663499484198

通过测试结果可以看出,main线程很快就返回了,而实际处理事件的线程是pool-1-thread-1,等待了3s多才返回。

ApplicationListener异步执行源码分析

参考:Spring注解驱动之ApplicationListener用法
与上面同步执行不同的地方就是使用了自定义的多波器里面的线程池执行了事件处理。
在这里插入图片描述
多波器的获取。
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

融极

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值