前言
spring的事件驱动模型,想必大家都比较熟,今天就来水一期,如何使用事件条件来进行事件触发。直接上示例
正文
注: 本示例主要模拟当用户注册,发送阿里云短信,模拟下单,发送腾讯云短信,模拟发送短信的逻辑,下放到事件监听里面做
1、模拟创建阿里云短信
public class AliyunSmsService implements SmsService {
@Override
public void sendSms(String phone, String content) {
System.out.printf("%s->使用阿里云短信【%s】发送成功!%n",phone,content);
}
}
2、创建短信事件
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class SmsEvent {
private String phone;
private String content;
private SmsEnums smsEnums;
}
3、模拟监听阿里云短信事件
@RequiredArgsConstructor
public class AliyunSmsListener {
private final AliyunSmsService aliyunSmsService;
@EventListener(condition = "#smsEvent.smsEnums.name().equalsIgnoreCase('aliyun')")
public void listener(SmsEvent smsEvent){
aliyunSmsService.sendSms(smsEvent.getPhone(),smsEvent.getContent());
}
}
4、模拟用户注册
@Service
@RequiredArgsConstructor
public class UserService {
private final ApplicationContext applicationContext;
public void mockRegister(String username,String phone){
System.out.println("用户注册成功,用户名:"+username);
SmsEvent smsEvent = SmsEvent.builder().phone(phone).content("欢迎注册").smsEnums(SmsEnums.ALIYUN).build();
applicationContext.publishEvent(smsEvent);
}
}
注: 模拟下单和用户注册,流程基本一样,就不贴代码了
5、测试验证
@Test
public void testAliyunSms(){
userService.mockRegister("lybgeek","13800000001");
}
@Test
public void testTencentSms(){
orderService.mockOrder("lybgeek","13800000002");
}
测试结果
a、当模拟用户注册时,控制台输出
会发现只会触发阿里云短信事件的发送
b、当模拟下单时,控制台输出
会发现只会触发腾讯云短信事件的发送
实现核心逻辑
通过在@EventListener的condition配置spel条件表达式,当condition为空时,默认事件都会触发,如果有指定相应的spel条件表达式,则会按条件表达式,再进行一层过滤
具体源码片段
org.springframework.context.event.ApplicationListenerMethodAdapter#processEvent
private boolean shouldHandle(ApplicationEvent event, @Nullable Object[] args) {
if (args == null) {
return false;
}
String condition = getCondition();
if (StringUtils.hasText(condition)) {
Assert.notNull(this.evaluator, "EventExpressionEvaluator must not be null");
return this.evaluator.condition(
condition, event, this.targetMethod, this.methodKey, args, this.applicationContext);
}
return true;
}
public void processEvent(ApplicationEvent event) {
Object[] args = resolveArguments(event);
if (shouldHandle(event, args)) {
Object result = doInvoke(args);
if (result != null) {
handleResult(result);
}
else {
logger.trace("No result object given - no result to handle");
}
}
}
总结
看完也许有朋友会说,我直接在监听类方法里,写if-else也可以达到效果啊,为啥那么麻烦。如果业务没那么复杂的话,可以这么做,但是我们本身使用事件就是为了解耦,如果在事件监听里面写一堆if-else,一来职责不够单一,二来我们更提倡对修改关闭,对扩展开放
demo链接
點(diǎn)擊查看更多內(nèi)容
為 TA 點(diǎn)贊
評(píng)論
評(píng)論
共同學(xué)習(xí),寫(xiě)下你的評(píng)論
評(píng)論加載中...
作者其他優(yōu)質(zhì)文章
正在加載中
感謝您的支持,我會(huì)繼續(xù)努力的~
掃碼打賞,你說(shuō)多少就多少
贊賞金額會(huì)直接到老師賬戶
支付方式
打開(kāi)微信掃一掃,即可進(jìn)行掃碼打賞哦