谈谈Spring中的事件模型
1 : 什么是Sping的事件
Spring的事件(ApplicationEvent)是为了提供Spring中对象(Bean)与对象之间的消息通信支持,也就是当一个bean处理完一个任务之后,想要另外一个bean知道,并能做出相应的处理,这个时候我们就需要另外一个bean监听到这个bean的消息。
2:业务场景
我们在处理完一段业务逻辑后,要给C端用户一个通知,很多地方都需要进行通知,每次new对象insert很麻烦,我们就可以用这个事件模型进行发布,在监听逻辑中处理,使我们代码之间的耦合度降低 提高效率。
3:怎么做
sping的事件需要遵从以下原则
①:自定义事件 继承ApplicationEvent
package com.dubug.middleware.entity;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.ApplicationEvent;
import java.io.Serializable;
import java.util.Date;
@ToString
@Getter
@Setter
public class DbPushMessage extends ApplicationEvent implements Serializable {
private String id;
private String userId;
private String messageType;
private String explain;
private Date pushTime;
public DbPushMessage(Object source, String id, String userId, String messageType, String explain, Date pushTime) {
super(source);
this.id = id;
this.userId = userId;
this.messageType = messageType;
this.explain = explain;
this.pushTime = pushTime;
}
}
② : 事件监听器
package com.dubug.middleware.listener;
import com.dubug.middleware.entity.DbPushMessage;
import com.dubug.middleware.mapper.DbPushMessageMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
/**
* @Description
* @Author 事件监听器 监听 DbPushMessage
* 1: 实现 ApplicationListener 接口 并指定监听的bean
* 2:实现 onApplicationEvent 方法 对消息进行处理
* @Version V1.0.0
* @Date 2021/6/9 0009
*/
@Slf4j
@Component
public class PushMessageListener implements ApplicationListener<DbPushMessage> {
@Autowired
private DbPushMessageMapper dbPushMessageMapper;
@Override
public void onApplicationEvent(DbPushMessage event) {
Assert.notNull(event);
log.info("监听到了事件:{}",event);
dbPushMessageMapper.insert(event); //保存到数据库
}
}
③: 事件发布类
package com.dubug.middleware.push;
import com.dubug.middleware.entity.DbPushMessage;
import com.dubug.middleware.util.IdGeneratorRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @Description
* @Author 事件发布类
* 1:注入ApplicationContext 用来发布事件
* 2:使用 ApplicationContext 的publishEvent 方法来发布
*
* @Version V1.0.0
* @Date 2021/6/9 0009
*/
@Slf4j
@Component
public class PushMessagePush {
@Autowired
private ApplicationContext applicationContext;
public void publish(String userId,String messageType,String explain){
log.info("发布了事件{}",dbPushMessage);
DbPushMessage dbPushMessage = new DbPushMessage(this,IdGeneratorRegistry.getId(),userId,messageType,explain,new Date());
applicationContext.publishEvent(dbPushMessage);
}
}
④: SpringBoot单元测试
package com.dubug.middleware.messageTest;
import com.dubug.middleware.applicationTest.ApplicationTest;
import com.dubug.middleware.push.PushMessagePush;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.HashMap;
import java.util.Map;
/**
* @Description
* @Author 单元测试
* @Version V1.0.0
* @Date 2021/6/9 0009
*/
public class MessageTest extends ApplicationTest {
@Autowired
private PushMessagePush pushMessagePush;
Map<String,String> beforeBean = new HashMap<>();
@Before
public void beforeBean(){
beforeBean.put("1","tom");
beforeBean.put("2","any");
}
@Test
public void testPush(){
pushMessagePush.publish(beforeBean.get("1"),"system_message","测试消息模型发布");
}
}
看下运行结果
总结
Spring的事件驱动模型可以帮我们更好的处理bean与bean直接的链接,同时也帮助我们降低了业务之间的耦合度,使我们更专注于业务代码的开发。
解决问题的过程是令人痛苦的,但是之后便是无比的成就感