spring的事件发布机制publsh-event

39 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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方法。

image.png

image.png

通知监听者的时候,会去检查ApplicationEventMulticaster对象中是否配置了Executor执行器,如果配置了的话,会将invokeListener(listener, event)封装成一个线程可执行任务,然后给执行器执行。