开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情
Spring的publish-event使用的是监听者模式。用于业务代码进行解耦,通常在一个复杂的逻辑业务里面,会包含一个核心业务和N个子业务,有些子业务,我们是不需要在当前请求中同步完成的,例如短信发送等。可以考虑使用Spring Event,它相当于一个观察者模式,当一个Bean完成任务之后,会通知另一个Bean去执行相应的任务。
Spring Retry也是Spring里的一个组件,主要实现是发生异常后重新调用。当一些瞬时错误(例如网络问题)发生时,Spring Retry的重试可以帮我们避免这种异常造成的服务调用失败的情况。
一、创建publsh-event监听
1、定义事件类,事件类继承ApplicationEvent
public class TestEvent extends ApplicationEvent {
private String name;
private String text;
public TestEvent(Object source, String name, String text) {
super(source);
this.name=name;
this.text=text;
}
public String getName() {
return name;
}
public String getText() {
return text;
}
}
2、定义事件监听类,必须实现ApplicationListener,并指定泛型为我们的自定义事件
@Component
public class TestEventListener implements ApplicationListener<TestEvent> {
@Override
public void onApplicationEvent(TestEvent testEvent) {
System.out.println("事件监听到了:"+testEvent.getName()+testEvent.getText());
}
}
3、发布事件
@Component
public class TestEventPublisher {
@Autowired
private ApplicationContext applicationContext;
public void publish(TestEvent testEvent){
applicationContext.publishEvent(testEvent);
}
}
也可以直接通过 @EventListener 监听事件类,更便捷,当然需要加上添加@EnableAsync和@EnableRetry注解。
第一步也是定义事件类,第二步定义事件监听类。
@Data
@AllArgsConstructor
public class MsgEvent {
private String msgId;
}
@Component
@Slf4j
public class MsgListener {
@EventListener
@Async
@Retryable(value = Exception.class,maxAttempts = 3,backoff = @Backoff(delay = 2000,multiplier = 1.5))
public void sendMsg(MsgEvent event) {
String msgId = event.getMsgId();
StopWatch watch = new StopWatch(msgId);
watch.start();
log.info("开始发短信");
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
watch.stop();
log.info("短信发送成功, 消息id:【{}】 | 耗时: ({})", msgId, watch.getLastTaskTimeMillis());
}
}
Retryable的参数介绍:
-
value值表示当哪些异常的时候触发重试
-
maxAttempts表示最大重试次数默认为3
-
delay表示重试的延迟时间
-
multiplier表示上一次延时时间是这一次的倍数
二、监听者模式跟观察者模式的区别
监听者模式包含了一个监听者Listener与之对应的事件Event,还有一个事件发布者EventPublish,过程就是EventPublish发布一个事件,被监听者捕获到,然后执行事件相应的方法
观察者模式是一对多的模式,一个被观察者Observable和多个观察者Observer,被观察者中存储了所有的观察者对象,当被观察者接收到一个外界的消息,就会遍历广播推算消息给所有的观察者
三、publishEvent原理
applicationContext.publishEvent(event)内部其实调用了ApplicationEventMulticaster的multicastEvent方法。
通知监听者的时候,会去检查ApplicationEventMulticaster对象中是否配置了Executor执行器,如果配置了的话,会将invokeListener(listener, event)封装成一个线程可执行任务,然后给执行器执行。