本文已参与「新人创作礼」活动,一同开启创作之路。
前言
该文章是我学习运用SpirngEvent的进程,现在只写了SpringEvent的运用,后续会写一篇从源码关注SpringEvent的完成进程。
后续篇章:SpringEvent 事情发布/监听机制相关源码解析
SpringEvent的介绍
SpringEvent是一个解决事务解耦的办法,运用了观察者模式,用于当一个事务的更改后,需求改变其他事务的状况。例如一个商品的下单,需求修改商品的库存,以及商家的音讯发送等等。之前我做这种事务解耦的时分,运用的是音讯行列进行解耦,但假如仅仅为了解耦而整合了音讯行列,就有点重了。我认为可以运用这种事务解耦需求满意下面的条件:
- 当做完事务的时分,不清楚有多少个子事务要进行更改,例如安防设备的报警,初期可能仅仅发送音讯到持有设备的用户,页面显示报警状况,后期或许会涉及到同步到其他平台事务、和其他安防设备产生连锁报警事务等等。
SpringEvent的运用
环境装备
JDK8
Spring boot 2.6.10
事务场景
当电脑发动的时分,电脑的自启程序需求发动,程序的服务也需求发动等等。
完成
创立ComputerStartEvent
电脑发动事情类
/**
* 电脑发动事情类
*/
public class ComputerStartEvent extends ApplicationEvent {
private ComputerEntity computerEntity;
public ComputerEntity getComputerEntity() {
return computerEntity;
}
public ComputerStartEvent(ComputerEntity source) {
super(source);
this.computerEntity=source;
}
}
创立AutoStartupSoftwareListener
自启软件发动监听类
/**
*
* 自启软件发动监听类
*/
@Component
public class AutoStartupSoftwareListener implements ApplicationListener<ComputerStartEvent> {
@Override
public void onApplicationEvent(ComputerStartEvent event) {
ComputerEntity computer=event.getComputerEntity();
System.out.println("电脑"+computer.getName()+"的自启软件正在进行");
}
}
创立ProgramServiceStartupListener
程序服务发动监听类
/**
* 程序服务发动监听类
*/
@Component
public class ProgramServiceStartupListener implements ApplicationListener<ComputerStartEvent> {
@Override
public void onApplicationEvent(ComputerStartEvent event) {
ComputerEntity computer=event.getComputerEntity();
System.out.println("电脑"+computer.getName()+"的程序服务正在发动");
}
}
客户端代码
poublic class ComputerService {
@Resource
private ApplicationEventPublisher applicationEventPublisher;
public void computerStart() {
ComputerEntity computer=new ComputerEntity();;
computer.setComputerId("dafdasf");
computer.setName("电脑A");
// 电脑发动操作
System.out.println(computer.getName()+"电脑发动了");
//发布电脑发动事情
applicationEventPublisher.publishEvent(new ComputerStartEvent(computer));
}
}
作用
异步完成
目前有两种办法可以完成异步,
- 一种是运用@EnableAsync和@Async发动异步。
- 一种是给Springboot的默认完成
SimpleAsyncEventMulticaster
类中的taskExecutor
字段赋值一个线程池。
一、运用@EnableAsync和@Async发动异步
下面为了演示异步的作用,自启软件的监听类不运用异步,程序服务的监听类运用异步,然后每个办法打印当前线程的Id。
AutoStartupSoftwareListener
自启软件发动监听类
/**
* 自启软件发动监听类
*/
@Component
public class AutoStartupSoftwareListener implements ApplicationListener<ComputerStartEvent> {
@Override
public void onApplicationEvent(ComputerStartEvent event) {
ComputerEntity computer=event.getComputerEntity();
System.out.println("电脑"+computer.getName()+"的自启软件正在进行");
//打印线程Id
System.out.println("AutoStartupSoftwareListener监听线程id:"+Thread.currentThread().getId());
}
}
ProgramServiceStartupListener
程序服务发动监听类
/**
* 程序服务发动监听类
*/
@EnableAsync
@Component
public class ProgramServiceStartupListener implements ApplicationListener<ComputerStartEvent> {
@Override
@Async
public void onApplicationEvent(ComputerStartEvent event) {
ComputerEntity computer=event.getComputerEntity();
System.out.println("电脑"+computer.getName()+"的程序服务正在发动");
//打印线程Id
System.out.println("ProgramServiceStartupListener监听线程id:"+Thread.currentThread().getId());
}
}
客户端代码
poublic class ComputerService {
@Resource
private ApplicationEventPublisher applicationEventPublisher;
public void computerStart() {
ComputerEntity computer=new ComputerEntity();;
computer.setComputerId("dafdasf");
computer.setName("电脑A");
// 电脑发动操作
System.out.println(computer.getName()+"电脑发动了");
//发布电脑发动事情
applicationEventPublisher.publishEvent(new ComputerStartEvent(computer));
//打印线程Id
System.out.println("computerStart办法线程id:"+Thread.currentThread().getId());
}
}
作用
异步启用成功
二、给SimpleAsyncEventMulticaster
类中的taskExecutor
字段赋值线程池
创立SimpleAsyncEventMulticaster
继承SimpleApplicationEventMulticaster
//需求指定下beanName
@Component("applicationEventMulticaster")
public class SimpleAsyncEventMulticaster extends SimpleApplicationEventMulticaster {
public SimpleAsyncEventMulticaster(){
ThreadPoolTaskExecutor taskExecutor=new ThreadPoolTaskExecutor();
taskExecutor.initialize();
taskExecutor.setCorePoolSize(5);
taskExecutor.setMaxPoolSize(100);
taskExecutor.setQueueCapacity(1000);
taskExecutor.setThreadNamePrefix("test-async");
setTaskExecutor(taskExecutor);
}
}
作用
两种异步的区别
假如给SimpleAsyncEventMulticaster
的taskExecutor
字段赋值线程池,一切监听类的执行都会是异步的,假如想要个别的任务执行是异步的话,需求重写SimpleAsyncEventMulticaster
的multicastEvent
办法,而运用@Async则不会,这也是为啥引荐的都是@Async办法完成异步。
总结
本文章介绍了SpringEvent和运用条件以及实例,这儿没有写源码的解析,因为比较长,上述内容假如有误人子弟的地方,望在评论区留言。