- 发短信案例问题分析
- 利用Spring事件机制完成需求
- Spring发布异步事件
发短信案例问题分析
假设现在有这么一个业务场景:
用户在京西商城下单成功后,平台要发送短信通知用户下单成功
我们最直观的想法是直接在order()方法中添加发送短信的业务代码:
public
咋一看没什么不妥,但是如果我们加上一根时间轴,那么代码就有问题了:
一个月后,京西搞了自建物流体系,用户下单成功后,需要通知物流系统发货
于是你又要打开OrderService修改order()方法:
public
嗯,完美。
又过了一个月,东哥被抓了,股价暴跌,决定卖掉自己的车队,所以下单后就不用通知车队了
重新修改OrderService:
public
又过了一个月,东哥明尼苏达州荣耀归来:回来做我的兄弟一起开车吧。
好的,东哥。
public
车队回来了,你却受不了这大起大落异常刺激的生活,决定离职。
就在这时候,组长拉住了你,语重心长地和你说:
小伙子,知道什么叫“以增量的方式应对变化的需求”吗?听过Spring监听机制吗?
说时迟那时快,组长拿来一支笔和一张纸,唰唰唰画了一张图:
你顿时心领神会,扑通一声跪在了地上,开始敲起了代码。
利用Spring事件机制完成需求
环境准备
<?xml version="1.0" encoding="UTF-8"?>
OrderService
/**
OrderSuccessEvent(继承ApplicationEvent,自定义事件)
public
SmsService(实现ApplicationListener,监听OrderSuccessEvent)
/**
Test
@RunWith
输出:
下单成功...
发送短信...
main线程结束...
如果后期针对下单成功有新的操作,可以新写一个事件监听类:
/**
这就是“以增量的方式应对变化的需求”,而不是去修改已有的代码。假设有B接口调用了C接口,你修改了C接口,那么B接口可能业务结果就错了,此时调用B接口的A接口也可能受到影响,是连锁反应。所以,一般我们都提倡“对扩展开放,对修改关闭”的原则。
上面SmsService既是一个服务,还是一个Listener,因为它既有@Service又实现了ApplicationListener接口。
但是仅仅是为了一个监听回调方法而实现一个接口,未免麻烦,所以Spring提供了注解的方式:
/**
Spring发布异步事件
看似很完美了,但是你注意到Spring默认的事件机制是同步的:
如果针对OrderService下单成功的操作越来越多,比如下单后需要完成的对应操作有十几个,那么等十几个其他服务都调用完毕,东哥可能又去明尼苏达州了。
所以,你必须想办法把Spring的事件机制改成异步的,尽可能快地返回下单的结果本身,而不是等其他附属服务全部完成(涉及到其他问题暂时按下不表)。
要想把Spring事件机制改造成异步通知,最粗暴的方法是:
OrderService
/**
SmsService
/**
输出:
下单成功...
main线程结束...
发送短信...
当然,这种做法其实违背了Spring事件机制的设计初衷。人家会想不到你要搞异步通知?
当SimpleApplicationEventMulticaster中的Executor不为null,就会执行异步通知。
@Configuration
不好意思,谅解下,肚子饿了,不想解释细节了。
想知道原理的,看另一篇文章:《自定义Spring事件监听机制》
当然了,最后还是要说一句,项目并发高了以后,也不可能用Spring监听机制的,MQ会更合适些。
2020-01-05 17:28:14