有这么一个业务场景:当用户注册后,发送邮件到其邮箱提示用户进行账号激活,且注册成功的同时需要赠送新人用户体验卡券。

业务有了,那么问题也就来了。

What? 问题....问题?我听说你有问题? 来拔刀吧,互相伤害啊。



考虑以下两个问题:如何注册成功立即发送邮件、赠送体验卡? 如何同时向用户邮箱发送激活邮件、赠送新人客户体验卡,互不影响?



如果是微服务项目,该逻辑可结合消息中间件进行处理。若是单机代码,有什么好的办法哇?你还在疯狂的代码逻辑判断吗?若代码高耦合,后期进行维护仿佛并不是那么happy,就不用说在此基础上扩展业务了。

So 请了解下Spring中事件机制:发布ApplicationEventPublisher,实现监听ApplicationEvent。结合异步操作,哎呀,真香!你值得拥有!



下面就跟着楼主的小碎步,慢慢带你带入坑。“气死我了,上才艺。EG埃meng,EG埃meng,EG埃meng。你说我是.....”

说归说,闹归闹,不拿代码开玩笑。回归正题,直接上代码。哇哈哈哈哈哈哈......

一、 首先定义下用户类:

楼主示例这个用户类属性写的比较随意,只做测试看效果哈。

二、定义一个Event事件类:

注意:自定义事件类继承ApplicationEvent类,重写方法



该类中属性根据业务需求自定义即可。

如下所示,楼主定义的Event类叫做UserActionEvent。



EnumUserOperate 枚举类

三、事件类定义好了,我们去定义操作发布:ApplicationEventPublisher,快点跟上别掉队了。

我是在UserServiceImpl中进行事件发布的,如下:



发布者会调用 ApplicationEventPublisher的publishEvent 方法对某一事件进行发布。随后Spring容器会把该事件告诉所有的监听者(我的“女神”有动态了),监听者根据拿到的“信息、某些指令或者某些数据”去做一些业务上的操作。

这个模式常常会与设计模式中观察者模式进行对比。举个栗子:上课铃响了,老师和同学听到铃声后,都来班里了(老师要上课,学生要听课)。在这个事件里,被观察的是“铃声”,“铃声响了”是一种状态,或者说是一种通知。告诉大家:该上课了。

四、发布事件后该定义监听了:

自定义监听方法上方添加注解:@EventListener()。

眼尖的小伙伴会发现,楼主这里使用表达式condition = "#event.operate.name()=='ADD'"对监听进行了细化:监听类型为“新增”的事件

注意:自定义监听必须交给spring容器管理,否则不起作用哈。如下图加@Component注解就行(兄弟,交保护费了。额....不交也行,但是必须得跟着spring混....)

@Async()会在下面说



发布和监听都设置好了,使用快乐的postman发送下请求......



测试结果如下:



加了表达式的只会监听到指定类型的事件。当然这里你可以加别的条件,根据业务怎么开心怎么来嘛,对不?

发布和监听可以了,那我并发操作的时候如何保证不会阻塞,互不影响呢?

异步啊,在加个线程池。

问一句:“老哥,为啥加线程池?”

多线程操作,反复创建销毁,性能消耗是很大的。使用线程池降低资源消耗,提高利用率,加上异步操作速度还快,何乐而不为呢。

五、方法异步:

定义方法上方加@Async()注解就好了。

异步方法可以指定使用某一线程池:如 @Async("lazyTraceExecutor"),lazyTraceExecutor是线程池Bean对象的名字

六、线程池自定义:

不知道有没有人diss楼主只截图,不贴代码。这不,他来了他来了....

@Configuration
public class Configurer implements AsyncConfigurer { // @Autowired
// private BeanFactory beanFactory; /**
* 自定义线程池
*
* @return
*/
@Bean("lazyTraceExecutor")
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//此方法返回可用处理器的虚拟机的最大数量; 不小于1
int core = Runtime.getRuntime().availableProcessors();
executor.setCorePoolSize(core);//设置核心线程数
executor.setMaxPoolSize(core * 2 + 1);//设置最大线程数
executor.setKeepAliveSeconds(3);//除核心线程外的线程存活时间
executor.setQueueCapacity(40);//如果传入值大于0,底层队列使用的是LinkedBlockingQueue,否则默认使用SynchronousQueue
executor.setThreadNamePrefix("my-executor-");//线程名称前缀
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());//设置拒绝策略
// return new LazyTraceThreadPoolTaskExecutor(beanFactory, executor);
executor.initialize(); return executor;
}
}

最后,别忘了在启动项上加@EnableAsync注解哦!

想了解ApplicationEventPublisher和ApplicationEvent原理的,认准spring官网happy哈。这里就不过多介绍了。

傲娇的wshanshi要go to sleep了。



靓女,帅仔。你有没有那个,那个小心心.... 没有!呸,渣男。啥也不是,散会!

示例代码可以点击此处下载:戳我戳我

SpringBoot 中发布ApplicationEventPublisher,监听ApplicationEvent 异步操作的更多相关文章

  1. SpringBoot | 第三十二章:事件的发布和监听

    前言 今天去官网查看spring boot资料时,在特性中看见了系统的事件及监听章节.想想,spring的事件应该是在3.x版本就发布的功能了,并越来越完善,其为bean和bean之间的消息通信提供了 ...

  2. SpringBoot系列——事件发布与监听

    前言 日常开发中,我们经常会碰到这样的业务场景:用户注册,注册成功后需要发送邮箱.短信提示用户,通常我们都是这样写: /** * 用户注册 */ @GetMapping("/userRegi ...

  3. spring中的事件发布与监听

    点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人. 文章不定期同步公众号,还有各种一线大厂面试原题.我的学习系列笔记. spring事件发布与监听的应用场景 当处理完一段代码逻辑,接下来需要同 ...

  4. Spring事件发布与监听机制

    我是陈皮,一个在互联网 Coding 的 ITer,微信搜索「陈皮的JavaLib」第一时间阅读最新文章,回复[资料],即可获得我精心整理的技术资料,电子书籍,一线大厂面试资料和优秀简历模板. 目录 ...

  5. spring 自定义事件发布及监听(简单实例)

    前言: Spring的AppilcaitionContext能够发布事件和注册相对应的事件监听器,因此,它有一套完整的事件发布和监听机制. 流程分析: 在一个完整的事件体系中,除了事件和监听器以外,还 ...

  6. Spring知识点回顾(07)事件发布和监听

    Spring知识点回顾(07)事件发布和监听 1.DemoEvent extends ApplicationEvent { public DemoEvent(Object source, String ...

  7. SpringBoot入门之事件监听

    spring boot在启动过程中增加事件监听机制,为用户功能拓展提供极大的便利,sptingboot支持的事件类型有以下五种: ApplicationStartingEvent Applicatio ...

  8. Fragment中的按键监听

    在Fragmentzhong中写按键监听,有两处处需要注意: 1)是否是当前显示的fragment:. 2)在所依托的activity中的onKeyDown方法处理监听事件: 其他地方和普通按键监听一 ...

  9. jQuery中的事件监听方式及异同点

    jQuery中的事件监听方式及异同点 作为全球最知名的js框架之一,jQuery的火热程度堪称无与伦比,简单易学的API再加丰富的插件,几乎是每个前端程序员的必修课.从读<锋利的jQuery&g ...

随机推荐

  1. 取得get参数 从url

    1. getUrlParam.js define(function() { // url参数 var data, index; (function init() { data = []; index ...

  2. Vue 初学

    Vue 的基本代码:      概念简介:Vue.js 是目前最火的一个前端框架,只关注视图层,主要负责MVC中的V这一层     MVC 是后端的分层开发概念:     MVVM是前端视图层的概念, ...

  3. layui 利用js原型方法来加载函数

    //举例如下: !function (win) { var FUNC = function () { this.v = "3.3" }; //这里添加函数 FUNC.prototy ...

  4. 『Python』面向对象(二)

    继承 继承的语法 class Animal(object): def __init__(self,name): self.__name = name class Dog(Animal): kind = ...

  5. P7854-「EZEC-9」GCD Tree【构造】

    正题 题目连接:https://www.luogu.com.cn/problem/P7854 题目大意 给出\(n\)数字的一个序列\(a\). 现在要求构造一棵树,使得对于任意的\((x,y)\)都 ...

  6. Python3入门系列之-----算术运算符|比较运算符|赋值运算符|逻辑运算符|成员运算符|身份运算符

    什么是运算符? 本章节主要说明Python的运算符.举个简单的例子 1 +2 = 3 . 例子中,1 和 1.2 被称为操作数,"+" 称为运算符. Python语言支持以下类型的 ...

  7. Go变量与基础数据类型

    一.基础介绍 Go 是静态(编译型)语言,是区别于解释型语言的弱类型语言(静态:类型固定,强类型:不同类型不允许直接运算) 例如 python 就是动态强类型语言 1.Go 的特性: 跨平台的编译型语 ...

  8. JVM学习笔记——栈区

    栈区 Stack Area 栈是运行时的单位,堆是存储单位,栈解决程序的运行问题,即程序如何执行,如何处理数据. 每个线程在创建时都创建一个该线程私有的虚拟机栈,每个栈里有许多栈帧,一个栈帧对应一个 ...

  9. CefSharp基于.Net Framework 4.0 框架编译

    CefSharp基于.Net Framework 4.0 框架编译 本次源码使用的是Github上CefSharp官方的79版本源码 准备 IDE Visual Studio 2017 Enterpr ...

  10. nginx配置禁止爬虫配置

    1.在配置文件里添加禁止爬虫配置 server { ------ #添加如下内容即可防止爬虫 if ($http_user_agent ~* "qihoobot|Baiduspider|Go ...