SpringBoot实现异步事件驱动的方法
目录
- Spring事件驱动
- 源码实战
@Servicepublic class ProductServiceImpl { ...public void saveProduct(Product product) {productMapper.saveOrder(product); notifyService.notify(product); } ...}
很简单并且很常见的一段业务逻辑:首先将产品先保存数据库,然后发送通知。
某一天你们可能需要把新增的产品存到Es中,这时候也需要代码可能变成这样:
@Servicepublic 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以实现事件监听。
- 自定义需要发布的事件类,需要继承ApplicationEvent类
- 使用ApplicationEventPublisher来发布自定义事件
- 使用@EventListener来监听事件
源码实战
创建事件
public class ProductEvent extends ApplicationEvent {public ProductEvent(Product product) {super(product); }}
发布事件
@Servicepublic class ProductServiceImpl implements IproductService { ...@Autowiredprivate ApplicationEventPublisher publisher; @Override@Transactional(rollbackFor = Exception.class)public void saveProduct(Product product) {productMapper.saveProduct(product); //事件发布publisher.publishEvent(product); }...}
事件监听
@Slf4j@AllArgsConstructorpublic 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@EnableAsyncpublic class ApplicationBootstrap {...}
使用了Async后会使用默认的线程池SimpleAsyncTaskExecutor,一般我们会在项目中自定义一个线程池。
@Configurationpublic 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实现异步事件驱动的方法的文章就介绍到这了,更多相关SpringBoot 异步事件驱动内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
推荐阅读
- Activiti(一)SpringBoot2集成Activiti6
- 关于QueryWrapper|关于QueryWrapper,实现MybatisPlus多表关联查询方式
- MybatisPlus使用queryWrapper如何实现复杂查询
- python学习之|python学习之 实现QQ自动发送消息
- 孩子不是实现父母欲望的工具——林哈夫
- SpringBoot调用公共模块的自定义注解失效的解决
- opencv|opencv C++模板匹配的简单实现
- Node.js中readline模块实现终端输入
- 解决SpringBoot引用别的模块无法注入的问题
- java中如何实现重建二叉树