SpringBoot实现异步事件驱动的方法

 更新时间:2021年06月28日 11:35:12   作者:飘渺Jam  
本文主要介绍了SpringBoot实现异步事件驱动的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在项目实际开发过程中,我们有很多这样的业务场景:一个事务中处理完一个业务逻辑后需要跟着处理另外一个业务逻辑,伪码大致如下:

@Service
public class ProductServiceImpl {
 ...
    public void saveProduct(Product product) {
        productMapper.saveOrder(product);
        notifyService.notify(product);
    }
 ...
}

很简单并且很常见的一段业务逻辑:首先将产品先保存数据库,然后发送通知。

某一天你们可能需要把新增的产品存到Es中,这时候也需要代码可能变成这样:

@Service
public class ProductServiceImpl {
 ...
    public void saveProduct(Product product) {
        productMapper.saveProduct(product);
        esService.saveProduct(product)
        notifyService.notify(product);
    }
 ...
}

随着业务需求的变化,代码也需要跟着一遍遍的修改。而且还会存在另外一个问题,如果通知系统挂了,那就不能再新增产品了。

对于上面这种情况非常适合引入消息中间件(消息队列)来对业务进行解耦,但并非所有的业务系统都会引入消息中间件(引入会第三方架构组件会带来很大的运维成本)。

Spring提供了事件驱动机制可以帮助我们实现这一需求。

Spring事件驱动

spring事件驱动由3个部分组成

  • ApplicationEvent:表示事件本身,自定义事件需要继承该类,用来定义事件
  • ApplicationEventPublisher:事件发送器,主要用来发布事件
  • ApplicationListener:事件监听器接口,监听类实现ApplicationListener 里onApplicationEvent方法即可,也可以在方法上增加@EventListener以实现事件监听。

实现Spring事件驱动一般只需要三步:

  • 自定义需要发布的事件类,需要继承ApplicationEvent类
  • 使用ApplicationEventPublisher来发布自定义事件
  • 使用@EventListener来监听事件

这里需要特别注意一点,默认情况下事件是同步的。即事件被publish后会等待Listener的处理。如果发布事件处的业务存在事务,监听器处理也会在相同的事务中。如果需要异步处理事件,可以onApplicationEvent方法上加@Aync支持异步或在有@EventListener的注解方法上加上@Aync。

源码实战

创建事件

public class ProductEvent extends ApplicationEvent {
    public ProductEvent(Product product) {
        super(product);
    }
}

发布事件

@Service
public class ProductServiceImpl implements IproductService {
 ...
    @Autowired
    private ApplicationEventPublisher publisher;
 
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveProduct(Product product) {
  productMapper.saveProduct(product); 
        //事件发布
        publisher.publishEvent(product);
    }
    ...
}

事件监听

@Slf4j
@AllArgsConstructor
public class ProductListener {

 private final NotifyService notifyServcie;

 @Async
 @Order
 @EventListener(ProductEvent.class)
 public void notify(ProductEvent event) {
  Product product = (Product) event.getSource();
  notifyServcie.notify(product, "product");
 }
}

在SpringBoot启动类上增加@EnableAsync 注解

@Slf4j
@EnableSwagger2
@SpringBootApplication
@EnableAsync
public class ApplicationBootstrap {
...
}

使用了Async后会使用默认的线程池SimpleAsyncTaskExecutor,一般我们会在项目中自定义一个线程池。

@Configuration
public class ExecutorConfig {
    /** 核心线程数 */
    private int corePoolSize = 10;
    /** 最大线程数  */
    private int maxPoolSize = 50;
    /** 队列大小  */
    private int queueCapacity = 10;
    /** 线程最大空闲时间   */
    private int keepAliveSeconds = 150;

    @Bean("customExecutor")
    public Executor myExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setThreadNamePrefix("customExecutor-");
        executor.setKeepAliveSeconds(keepAliveSeconds);

        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

到此这篇关于SpringBoot实现异步事件驱动的方法的文章就介绍到这了,更多相关SpringBoot 异步事件驱动内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java编程中的条件判断之if语句的用法详解

    Java编程中的条件判断之if语句的用法详解

    这篇文章主要介绍了Java编程中的条件判断之if语句的用法详解,是Java入门学习中的基础知识,需要的朋友可以参考下
    2015-11-11
  • kafka添加安全验证配置方式

    kafka添加安全验证配置方式

    这篇文章主要介绍了kafka添加安全验证配置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • SpringBoot实现数据源动态切换的最佳姿势

    SpringBoot实现数据源动态切换的最佳姿势

    这篇文章主要为大家详细介绍一下SpringBoot实现数据源动态切换的最佳姿势,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-03-03
  • 一篇文章带你入门java网络编程

    一篇文章带你入门java网络编程

    网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来。本文介绍了一些网络编程基础的概念,并用Java来实现TCP和UDP的Socket的编程,来让读者更好的了解其原理
    2021-08-08
  • 详解spring cloud整合Swagger2构建RESTful服务的APIs

    详解spring cloud整合Swagger2构建RESTful服务的APIs

    这篇文章主要介绍了详解spring cloud整合Swagger2构建RESTful服务的APIs,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • Java中的命名与目录接口JNDI基本操作方法概览

    Java中的命名与目录接口JNDI基本操作方法概览

    这篇文章主要介绍了Java中的命名与目录接口JNDI基本操作方法概览,JNDI提供统一的客户端API使得Java应用程序可以和这些命名服务和目录服务之间进行交互,需要的朋友可以参考下
    2016-03-03
  • Java 给PPT添加动画效果的示例

    Java 给PPT添加动画效果的示例

    这篇文章主要介绍了Java 给PPT添加动画效果的示例,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下
    2021-04-04
  • Java常见延迟队列的实现方案总结

    Java常见延迟队列的实现方案总结

    Java延迟队列(DelayQueue)是Java并发包中的一个类,它实现了BlockingQueue接口,且其中的元素必须实现Delayed接口,延迟队列中的元素按照延迟时间的长短进行排序,本文给大家介绍了Java常见延迟队列的实现方案总结,需要的朋友可以参考下
    2024-03-03
  • 详解java动态代理模式

    详解java动态代理模式

    这篇文章主要为大家详细介绍了java动态代理模式,总结一下代理模式,以及jdk,cglib代理模式用法,来理解代理模式,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • 代码分析Spring MVC的工作原理

    代码分析Spring MVC的工作原理

    在本篇文章里小编给大家整理了关于Spring MVC的工作原理的相关知识点以及实例代码内容,需要的朋友们可以参考下。
    2019-06-06

最新评论