Spring ApplicationEvent 异步处理

本文探讨了如何在Spring框架中使用@Async注解实现ApplicationEvent的异步处理,避免了不必要的同步操作,提升性能。通过实例说明了如何在监听器方法上添加@Async以实现实时异步执行。
摘要由CSDN通过智能技术生成

在性能要求比较高的接口中,执行一个比较耗时而并不关键的操作(比如上报监控信息什么的),如果同步执行必然是没有意义的,因此一般我们会想去异步处理,通常会使用MQ之类的中间件,不过Spring也提供了事件相关的处理,就是ApplicationEvent,关于这个类这里不再多言,基础的知识可以网上搜索相关教程,不过有一个问题需要注意的是,默认这种事件机制是同步的,好处是如果有事务,发送事件的方法和事件处理的方法在同一个事务里,缺点就是,可能并没有实现我们想象中的异步处理,有一种方案是在处理事件的时候使用一个线程池,通过线程池来异步处理,虽然是解决了异步的问题,但是给笔者一种脱裤子放屁的赶脚,与其这样,还不如直接扔到一个线程池里,何必还走一个事件处理?好在Spring本身也支持ApplicationEvent的异步处理,通过@Async注解就可以了,下面是相关代码:

首先是不使用@Async注解前,ApplicationEvent处理是同步的一个验证

先来一个事件

public class UploadEvent extends ApplicationEvent {
    public UploadEvent(Object source) {
        super(source);
    }
}

事件监听器

@Service
public class TEventListener implements ApplicationListener<UploadEvent> {
    @Override
    public void onApplicationEvent(UploadEvent uploadEvent) {
        try {
            System.out.println(">>>OK1");
            TimeUnit.SECONDS.sleep(5);
            System.out.println(">>>OK2");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

这里还需要用到Spring的上下文

@EnableAsync
@Component
public class SpringContextUtil implements ApplicationContextAware {
	private static ApplicationContext applicationContext; // Spring应用上下文环境
 
	/*
	 * 
	 * 实现了ApplicationContextAware 接口,必须实现该方法;
	 * 
	 * 通过传递applicationContext参数初始化成员变量applicationContext
	 * 
	 */
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		SpringContextUtil.applicationContext = applicationContext;
	}
 
	public static ApplicationContext getApplicationContext() {
		return applicationContext;
	}
 
	public static<T> T getBean(Class<T> requiredType) {
		return (T) applicationContext.getBean(requiredType);
	}
 
	public static void publishEvent(ApplicationEvent event){
		applicationContext.publishEvent(event);
	}
}

注意这里的@EnableAsync注解,这个是后面实现异步事件的必要配置,这里先写好,后面就不再复述了。

接下来是测试类

 @Test
    public void testEvent(){
        UploadEvent event = new UploadEvent(this);
        SpringContextUtil.publishEvent(event);
        System.out.println(">>>OK");
    }

执行后输出的结果是

OK1

OK2

OK

明显是同步的

那么怎么办呢?很简单,在监听器方法前加一个@Async注解

@Async
    @Override
    public void onApplicationEvent(UploadEvent uploadEvent) {
        try {
            System.out.println(">>>OK1");
            TimeUnit.SECONDS.sleep(5);
            System.out.println(">>>OK2");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

这时再执行测试方法,结果是

OK

OK1

OK2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值