该文章是我学习使用SpirngEvent的过程,现在只写了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 {
@Override
public void onApplicationEvent(ComputerStartEvent event) {
ComputerEntity computer=event.getComputerEntity();
System.out.println("电脑"+computer.getName()+"的自启软件正在进行");
}
}
ProgramServiceStartupListener
程序服务启动监听类/**
* 程序服务启动监听类
*/
@Component
public class ProgramServiceStartupListener implements ApplicationListener {
@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));
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LZyZUsxx-1659858328571)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/03b2625488424e38bd3809b266f901dc~tplv-k3u1fbpfcp-watermark.image?)]
目前有两种方式可以实现异步,
SimpleAsyncEventMulticaster
类中的taskExecutor
字段赋值一个线程池。下面为了演示异步的效果,自启软件的监听类不使用异步,程序服务的监听类使用异步,然后每个方法打印当前线程的Id。
AutoStartupSoftwareListener
自启软件启动监听类/**
* 自启软件启动监听类
*/
@Component
public class AutoStartupSoftwareListener implements ApplicationListener {
@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 {
@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());
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K2z7nDvA-1659858328573)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9abd7784e14144b3a122015105eb3dbb~tplv-k3u1fbpfcp-watermark.image?)]
异步启用成功
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);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i2f10oEh-1659858328574)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5bb01efec281429380788a4c9d3deb95~tplv-k3u1fbpfcp-watermark.image?)]
如果给SimpleAsyncEventMulticaster
的taskExecutor
字段赋值线程池,所有监听类的执行都会是异步的,如果想要个别的任务执行是异步的话,需要重写SimpleAsyncEventMulticaster
的multicastEvent
方法,而使用@Async则不会,这也是为啥推荐的都是@Async方式实现异步。
本文章介绍了SpringEvent和应用条件以及实例,这里没有写源码的解析,因为比较长,上述内容如果有误人子弟的地方,望在评论区留言。