Spring Events——事件监听机制
背景
高内聚低耦合,一直是我们软件开发者提倡的开发准则,然而在日常的开发中,产品日益迭代,代码堆砌、未及时小范围重构等,耦合性愈见严重。其实在日常的功能当中也可以做优雅的解耦。
常见的电商商会员注册场景:
- 注册新用户
- 优惠券和折扣:为新注册用户提供优惠券或折扣码,鼓励他们进行首次购买
- 积分奖励:引入积分系统,新用户注册后可以获得一定的积分,积分可以在未来的购物中使用,以此来增加用户的粘性
- 推荐奖励:实施推荐系统,当现有用户推荐新用户成功注册时,双方都可以获得一定的奖励,如优惠券、积分等
- 会员专属内容:提供会员专属的内容或服务,如会员专属的产品预览、特殊折扣日等,增加会员的专属感和归属感
- ...
可以看到,我们在注册会员这一个动作之后,常常需要多个地方关注这个动作。
当然,我们可以用组合模式
,然后在注册会员这个方法内,调用不同功能,比如:
/**
* 注册会员
*/
public void registerMember(RegisterParam param) {
// 参数校验
checkParam(param);
// 注册会员
registerService.register(param);
// 优惠券发放
couponService.grantCoupon(param);
// 积分奖励
pointService.awardPoint(param);
// ...
}
以上组合模式虽然代码也非常清晰(功能、职责),比直接在一个方法写所有逻辑要好很多。
但是,随着后期产品的迭代,我们的需求可能有 内部人员推荐、会员专属 内容等,然后继续在这一段完善功能:
/**
* 注册会员
*/
public void registerMember(RegisterParam param) {
// 参数校验
checkParam(param);
// 注册会员
registerService.register(param);
// 优惠券发放
couponService.grantCoupon(param);
// 积分奖励
pointService.awardPoint(param);
// 推荐奖励
recommendService.awardRecommend(param);
// 会员专属内容
memberContentService.sendContent(param);
// ...
}
你也看到了,如果继续产品迭代,可能会继续在 registerMember 做更多操作,这将存在几个明显的缺点:
- registerMember 方法臃肿,耦合严重,也并不满足
单一职责
; - 如果后续注册会员的需求频繁变更,相应就需要频繁变更 registerMember 方法,违反了
开闭原则
。
问
:有没有更好的方法解决呢?
当然有,观察者模式
你一定不陌生,我们将注册会员这一行为以事件
的形式发布出去,相关观察者监听到这一行为并进行处理,如下图:
- 首先,先处理与注册会员相关的主逻辑
- 然后,将发布
注册会员事件
,由相关监听者处理对应业务逻辑。
这样一来,即使后续功能迭代需要新增业务处理,我们可以很方便扩展监听者 listener,符合 单一职责
、开闭原则
。
问
:在 Spring 环境下,我们需要自定义观察者机制吗?
不用,Spring 有现成的的事件监听机制,符合我们当前的场景,接下来看看事件监听机制是如何处理~
实践
1、首先我们将会员注册定义为一个独立的事件:
public class RegisterMemberEvent extends ApplicationEvent {
private RegisterMemberInfo registerMemberInfo;
public RegisterMemberEvent(Object source) {
super(source);
}
public RegisterMemberEvent(Object source, RegisterMemberInfo registerMemberInfo) {
super(source);
this.registerMemberInfo = registerMemberInfo;
}
public RegisterMemberInfo getRegisterMemberInfo() {
return registerMemberInfo;
}
}
2、定义监听器
普通用法: 以发送积分奖励监听者为例
@Component
public class RegisterMemberListener implements ApplicationListener<RegisterMemberEvent> {
@Override
public void onApplicationEvent(RegisterMemberEvent event) {
// 积分奖励
awardPoint(param);
// 发送短信
sendSms(param);
// ...
}
}
当然,也可以直接用注解的形式:
public class RegisterMemberListener {
@EventListener(classes = RegisterMemberEvent.class)
@Order(0)
@Async
public void awardPoint(RegisterMemberEvent event) {
}
@EventListener(classes = RegisterMemberEvent.class)
@Order(0)
@Async
public void sendSms(RegisterMemberEvent event) {
}
}
3、事件发布
@Service
public class RegisterMemberService {
@Resource
private ApplicationEventPublisher applicationEventPublisher;
public void register() {
// 参数校验
checkParam(param);
// 注册会员
registerService.register(param);
applicationEventPublisher.publishEvent(new RegisterMemberEvent(this, new RegisterMemberInfo()));
}
}
至此,我们就优雅的解决了以上问题,接下来我们分析下 spring 事件监听机制原理。
小结
Spring ApplicationEvent 本质也是采用的观察者模式进行解耦设计,其内置了部分 Event 在 Spring 框架内部使用;
同时,我们也可以很灵活的定义业务层的事件类型,扩展性强,符合高内聚、低耦合特性。
尤其在一些复杂的业务场景下,对于功能解耦、后期扩展等都有很强的实用价值!
转载自:https://juejin.cn/post/7377662459920203813