本文已参与「新人创作礼」活动,一同开启创作之路。

前言

该文章是我学习运用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));
    }
}

作用

SpringEvent事件发布/监听机制的应用

异步完成

目前有两种办法可以完成异步,

  • 一种是运用@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());
    }
}

作用

SpringEvent事件发布/监听机制的应用
异步启用成功

二、给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);
    }
}

作用

SpringEvent事件发布/监听机制的应用

两种异步的区别

假如给SimpleAsyncEventMulticastertaskExecutor字段赋值线程池,一切监听类的执行都会是异步的,假如想要个别的任务执行是异步的话,需求重写SimpleAsyncEventMulticastermulticastEvent办法,而运用@Async则不会,这也是为啥引荐的都是@Async办法完成异步。

总结

本文章介绍了SpringEvent和运用条件以及实例,这儿没有写源码的解析,因为比较长,上述内容假如有误人子弟的地方,望在评论区留言。