SpringBoot 中发布ApplicationEventPublisher,监听ApplicationEvent 异步操作

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

在这里插入图片描述

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

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了。

在这里插入图片描述
靓女,帅仔。你有没有那个,那个小心心… 没有!呸,渣男。啥也不是,散会!

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

  • 129
    点赞
  • 192
    收藏
    觉得还不错? 一键收藏
  • 29
    评论
Spring Boot,我们可以使用ApplicationEventPublisher发布自定义事件。下面是一个简单的使用案例: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Component; @Component public class MyEventPublisher { @Autowired private ApplicationEventPublisher applicationEventPublisher; public void publishEvent(final String message) { System.out.println("Publishing custom event. "); MyEvent customSpringEvent = new MyEvent(this, message); applicationEventPublisher.publishEvent(customSpringEvent); } } ``` 在上面的代码,我们首先注入了ApplicationEventPublisher,然后定义了一个publishEvent方法,该方法接受一个字符串参数message。在该方法,我们创建了一个自定义事件MyEvent,并使用ApplicationEventPublisher发布了该事件。 下面是自定义事件MyEvent的定义: ```java import org.springframework.context.ApplicationEvent; public class MyEvent extends ApplicationEvent { private String message; public MyEvent(Object source, String message) { super(source); this.message = message; } public String getMessage() { return message; } } ``` 在上面的代码,我们继承了ApplicationEvent,并添加了一个message属性和相应的getter方法。 最后,我们需要定义一个事件监听器来处理自定义事件。下面是一个简单的事件监听器: ```java import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; @Component public class MyEventListener { @EventListener public void onApplicationEvent(MyEvent event) { System.out.println("Received spring custom event - " + event.getMessage()); } } ``` 在上面的代码,我们使用@EventListener注解来标记onApplicationEvent方法,该方法接受一个MyEvent参数。当MyEvent事件被发布时,该方法将被调用,并输出事件的message属性。
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值