单机服务可使用spring的监听事件与发布代替消息中间件进行解耦
单机服务使用消息中间件好像有点太奢侈了, mq一般场景都是用于分布式微服务架构系统, 通常用来: 解耦, 异步下单, 延迟场景, 削峰填谷等场景.
那么单机服务要使用监听与发布机制来进行解耦如何处理呢?
来看看使用spring的监听发布机制吧! 该机制也能在分布式微服务当中配合消息中间件等一系列解耦操作
事件的发布
public class MyBootApplication{
public static void main(String[] args) throws Exception {
ApplicationEventPublisher context = new AnnotationConfigApplicationContext(MyEventListener.class);
context.publishEvent(new MyEvent("hello world"));
}
}
自定义事件类
// 继承ApplicationEvent 事件类
public class MyEvent extends ApplicationEvent{
// 自定义需要的属性
private long userId;
// ....
public MyEvent (Object source, long userId /*....*/) {
super(source);
this.userId = userId;
/*....*/
}
}
事件监听
@Component
public class MyEventListener{
@org.springframework.context.event.EventListener
@Async
@Order(2) // 监听顺序
public void oneEvent(MyEvent event){
System.out.println("接收事件1" + event.getSource());
}
@org.springframework.context.event.EventListener
@Async
@Order(1) // 监听顺序
public void twoEvent(MyEvent event){
System.out.println("接收事件2" + event.getSource());
}
}
@Order注解表示监听顺序, 是否有必要处理需要根据具体业务场景判断
Debug启动后, 控制台显示如下信息:
@Order(1) 先执行, @Order(2) 后执行
以上只是一个简单的示例
下面来看下项目中的具体实践
启动类
@SpringBootApplication
@EnableAsync
// 正常启动类应该有多个注解, 比如注册中心的, 事务管理等等, 这里只展示SpringBootApplication 以及 EnableAsync注解
public class AccountApplication {
public static void main(String[] args) {
SpringApplication.run(AccountApplication.class, args);
}
}
自定义event
@Getter
@Setter
public class CreateUserEvent extends ApplicationEvent {
private String openId;
private BaseAccountLoginReq loginReq;
private MarketActivityDTO marketActivity;
CreateUserEvent(Object source, String openId, BaseAccountLoginReq loginReq, MarketActivityDTO marketActivity) {
super(source);
this.openId = openId;
this.loginReq = loginReq;
this.marketActivity = marketActivity;
}
}
这里只展示一个event, 实际有多个event类统一放在event包下面管理
发布事件
/**
* 用户事件发布器
*/
@Slf4j
@Component
public class AccountCenterEventPublisher {
@Resource
private ApplicationContext applicationContext;
/**
* 发布创建用户的事件
*
* @param loginReq
*/
public void publishCreateUserEvent(String openId, BaseAccountLoginReq loginReq, MarketActivityDTO marketActivity) {
applicationContext.publishEvent(new CreateUserEvent(this, openId, loginReq, marketActivity));
log.info("---------------AccountCenter Publisher send CreateUserEvent-------------------");
}
这里为啥要注入ApplicationContext呢?
仔细看ApplicationContext接口继承了ApplicationEventPublisher接口
这个就是事件发布器
点进去可以看到有 定义了 void publishEvent(Object var1); 该方法就是事件发布的方法
package org.springframework.context;
@FunctionalInterface
public interface ApplicationEventPublisher {
// 默认实现
default void publishEvent(ApplicationEvent event) {
this.publishEvent((Object)event);
}
// 事件发布
void publishEvent(Object var1);
}
所以自定义的event事件不一定要继承ApplicationEvent事件, 也可以直接用对象传入事件发布的方法中
分享一个有趣的事情, 可以尝试一下监听多种类型, 比如八大基础类型, 包装类等等
监听事件
/**
* 监听用户创建事件,发送MQ消息
*
* @param event
*/
@EventListener
@Async(value = "traceExecutor")
public void sendMQRegisterMessage(CreateUserEvent event) {
kafkaHelper.sendRegister(event.getOpenId(), event.getLoginReq(), event.getMarketActivity());
}
各位大佬看了如果对你有帮助的麻烦点点关注啊,有什么问题欢迎评论!!!