前言
咱们后面的文章中解说过RabbitMQ的用法,所谓MQ就是一种公布订阅模式的音讯模型。在Spring中其实自身也为咱们提供了一种公布订阅模式的事件处理形式,就是ApplicationEvent和 ApplicationListener,这是一种基于观察者模式实现事件监听性能。也已帮忙咱们实现业务逻辑的解耦,进步程序的扩展性和可维护性。
然而这里要留神ApplicationEvent和 MQ队列尽管实现的性能类似,然而MQ还是有其不可替代性的,最实质的区别就是MQ能够用于不同零碎之间的音讯公布,而SpringEvent这种模式只能在一个零碎中,也就是要求必须是同一个Spring容器。
好了接下来咱们就来演练一番。
在这个模型中,有两个重要的类,一个是事件,一个是监听。事件要继承ApplicationEvent类,监听要实现ApplicationListener接口。
一、开发ApplicationEvent事件
事件其实就是咱们要发送的音讯体,这个个别要依据咱们的理论业务进行封装,须要什么类型的数据,就是用什么类型,须要哪些字段就增加哪些字段。咱们来给一个案例。
package com.lsqingfeng.springboot.applicationEvent; import lombok.Getter;import lombok.Setter;import org.springframework.context.ApplicationEvent; /** * @className: MyApplicationEvent * @description: 事件封装 * @author: sh.Liu * @date: 2022-03-23 14:41 */@Getter@Setter@ToStringpublic class MyApplicationEvent extends ApplicationEvent { private Integer age; private String name; /** * 须要重写构造方法 * @param source * @param name * @param age */ public MyApplicationEvent(Object source, String name, Integer age) { super(source); this.name = name; this.age = age; }}
二、 开发监听器
监听器就相当于咱们的MQ的消费者,当有工夫推送过去的时候,监听器的代码就能够执行。这里通过泛型来设置好咱们的事件类型。
package com.lsqingfeng.springboot.applicationEvent; import org.springframework.context.ApplicationListener;import org.springframework.stereotype.Component; /** * @className: MyApplicationEventListener * @description:事件监听器 * @author: sh.Liu * @date: 2022-03-23 14:50 */@Componentpublic class MyApplicationEventListener implements ApplicationListener<MyApplicationEvent> { @Override public void onApplicationEvent(MyApplicationEvent event) { System.out.println("收到音讯:" + event); }}
三、推送事件
推送事件须要应用ApplicationEventPublisher。这个对象在Spring容器加载的时候就曾经在容器中了。所以咱们能够间接注入应用,也能够应用ApplicationContext,因为ApplicationContext自身就继承了ApplicationEventPublisher。 咱们通过一个Controller来验证一下。
package com.lsqingfeng.springboot.controller; import com.lsqingfeng.springboot.applicationEvent.MyApplicationEvent;import com.lsqingfeng.springboot.base.Result;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController; /** * @className: ApplicationEventController * @description: * @author: sh.Liu * @date: 2022-03-23 15:21 */@RestController@RequestMapping("event")public class ApplicationEventController { @Autowired private ApplicationContext applicationContext; @RequestMapping("/push") public Result pushEvent(){ MyApplicationEvent myApplicationEvent = new MyApplicationEvent(this,"zhangsan", 10); applicationContext.publishEvent(myApplicationEvent); return Result.success(); } @RequestMapping("/push2") public Result pushEvent2(){ applicationContext.publishEvent("大家好"); return Result.success(); }}
咱们定义两个推送的办法。一个推送咱们的MyApplicationEvent类型,还有一个办法推送一个字符串。
当咱们调用第一个办法的时候,控制台能够打印出咱们推送的数据信息。
调用推送字符串的时候,咱们的监听器不会执行,起因是咱们的拦截器里曾经加了泛型MyApplicationEvent,也就是只会监听MyApplicationEvent类型的音讯。其余类型的音讯不会被监听到。
那如果咱们把泛型去掉会有什么成果呢,咱们来试试。
每次推送都会发送两条(可能有什么外部机制,不论了),然而两个都打印了,阐明如果不加泛型,不论谁推,这边都能收到音讯。
四、注解形式实现监听器
除了下面的通过实现接口的形式开发监听器,咱们还能够通过注解的形式来实现,具体代码如下。
package com.lsqingfeng.springboot.applicationEvent; import org.springframework.context.event.EventListener;import org.springframework.stereotype.Component; /** * @className: MyApplicationEventListener2 * @description: 注解实现监听器 * @author: sh.Liu * @date: 2022-03-23 15:56 */@Componentpublic class MyApplicationEventListener2 { @EventListener public void onEvent(MyApplicationEvent event){ System.out.println("收到音讯2:" + event); } }
这里退出了@EventListener 注解代表了这是一个监听器。办法名随便,办法里的参数代表监听的事件类型。
再次调用push办法:
发现两个监听器的数据都会打印。这一特点大家要留神一下。
好了,对于Spring中的ApplicationEvent和ApplicationListener咱们就介绍这么多。