spring的事件(ApplicationEvent)为bean和bean之间的消息通信提供了支持。当bean处理完一个事件之后,希望另一个bean能够知道并做相应的处理。这时另一个bean监听当前bean所发送的事件。
spring的事件流程如下:
- 自己的event需要继承 ApplicationEvent,并且写相应的构造函数
- 定义一个监听器listener,实现ApplicationListener接口,重写onApplicationEvent方法
- 使用ApplicationContext容器发布事件
案例(伴有责任链模式设计)
创建一个DemoEvent
package com.lyj.demo.service.pushMsg;
import com.lyj.demo.constant.MsgListenerEnum;
import com.lyj.demo.pojo.Student;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.springframework.context.ApplicationEvent;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author 凌兮
* @date 2020/4/27 9:02
* 事件
*/
public class ListenerMsgPutEvent extends ApplicationEvent {
private Map<MsgListenerEnum,Object> msgListenerEnums;
private Long id;
private Student student;
public ListenerMsgPutEvent(Object source, Long id, Student student) {
super(source);
this.id = id;
this.student = student;
}
public Map<MsgListenerEnum, Object> getMsgListenerEnums() {
return msgListenerEnums;
}
public void setMsgListenerEnums(Map<MsgListenerEnum, Object> msgListenerEnums) {
this.msgListenerEnums = msgListenerEnums;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
@Override
public String toString(){
return ToStringBuilder.reflectionToString(this);
}
//
// public static void main(String[] args) {
// ListenerMsgPutEvent listenerMsgPutEvent = new ListenerMsgPutEvent(null,null,null,null);
// Map<MsgListenerEnum, Object> msgListenerEnumObjectMap = new HashMap<>();
// msgListenerEnumObjectMap.put(MsgListenerEnum.SUBMIT_RETURN_ORDER_REMARK,null);
// Student student = Student.builder()
// .id(1L)
// .age(22)
// .birth(new Date())
// .build();
//
// listenerMsgPutEvent.setMsgListenerEnums(msgListenerEnumObjectMap);
// listenerMsgPutEvent.setId(1L);
// listenerMsgPutEvent.setStudent(student);
// System.out.println(listenerMsgPutEvent.toString());
//
//
// }
}
创建事件监听者
package com.lyj.demo.listener;
import com.lyj.demo.mapper.StudentMapper;
import com.lyj.demo.pojo.Student;
import com.lyj.demo.service.pushMsg.ListenerMsgPutEvent;
import com.lyj.demo.service.pushMsg.MsgPutStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author 凌兮
* @date 2020/4/27 9:32
* 事件监听器
*/
@Component
@Slf4j
public class MsgHandlerListener implements ApplicationListener<ListenerMsgPutEvent> {
@Autowired
private StudentMapper studentMapper;
@Autowired
private List<MsgPutStrategy> msgPutStrategies;
/**
* 对监听到的事件进行处理
* @param listenerMsgPutEvent
*/
@Override
public void onApplicationEvent(ListenerMsgPutEvent listenerMsgPutEvent) {
Long id = listenerMsgPutEvent.getId();
Student student = studentMapper.selectById(id);
for (MsgPutStrategy msgPutStrategy :msgPutStrategies) {
try {
if (msgPutStrategy.choose(listenerMsgPutEvent.getMsgListenerEnums().keySet())){
msgPutStrategy.execute(listenerMsgPutEvent);
}
}catch (Exception e){
log.error("执行任务失败",e);
}
}
}
}
事件发布
package com.lyj.demo.service.pushMsg;
import com.lyj.demo.constant.MsgListenerEnum;
import com.lyj.demo.pojo.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import java.util.Map;
/**
* @author 凌兮
* @date 2020/4/27 10:04
* 事件发布
*/
@Service
public class MsgPutPublishServiceImpl {
/**
* 注入上下文对象(容器)
*/
@Autowired
private ApplicationContext applicationContext;
/**
* 配置事务,在spring事务提交之后进行异步操作,这些异步操作必须在
* 事务成功提交后才执行,回滚则不执行这些操作。
* @param id
* @param student
* @param msgListenerEnums
*/
@Transactional(rollbackFor = Exception.class)
public void publish(Long id, Student student, Map<MsgListenerEnum,Object> msgListenerEnums){
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
ListenerMsgPutEvent listenerMsgPutEvent = new ListenerMsgPutEvent(this, id, student);
listenerMsgPutEvent.setMsgListenerEnums(msgListenerEnums);
//发布事件
applicationContext.publishEvent(listenerMsgPutEvent);
}
});
}
}
责任链扩展接口
package com.lyj.demo.service.pushMsg;
import com.lyj.demo.constant.MsgListenerEnum;
import java.util.Set;
/**
* @author 凌兮
* @date 2020/4/27 9:35
*/
public interface MsgPutStrategy {
/**
* 是否选择此轨道
* @param msgListeners
* @return
*/
boolean choose(Set<MsgListenerEnum> msgListeners);
/**
* 执行监听事件
* @param listenerMsgPutEvent
*/
void execute(ListenerMsgPutEvent listenerMsgPutEvent);
}
执行策略1
package com.lyj.demo.service.pushMsg;
import com.lyj.demo.constant.EnumConstant;
import com.lyj.demo.constant.MsgListenerEnum;
import com.lyj.demo.pojo.Student;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Set;
/**
* @author 凌兮
* @date 2020/4/27 11:06
*增加学生信息事件处理
*/
@Service
@Slf4j
public class SubmitStudentStrategy extends AbstractMsgPutEvent {
/**
* 这个文件可以配置rabbitmq推送消息
* 这里只是模拟事件监听
* @param msgListeners
* @return
*/
@Override
public boolean choose(Set<MsgListenerEnum> msgListeners) {
return msgListeners.contains(MsgListenerEnum.SUBMIT_STUDENT_INFORMATION);
}
@Override
public void execute(ListenerMsgPutEvent listenerMsgPutEvent) {
Student student = listenerMsgPutEvent.getStudent();
try {
System.out.println(student.toString());
} catch (Exception e) {
log.error("SubmitStudentStategy error :{}",e);
saveFailMsg(EnumConstant.BusinessTypeEnums.INSERT_RECORD,student,String.valueOf(student.getId()));
}
}
}
执行策略二
package com.lyj.demo.service.pushMsg;
import com.lyj.demo.constant.EnumConstant;
import com.lyj.demo.constant.MsgListenerEnum;
import com.lyj.demo.pojo.Student;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Set;
/**
* @author 凌兮
* @date 2020/4/27 11:30
* 修改学生信息事件处理
*/
@Service
@Slf4j
public class UpdateStudentStategy extends AbstractMsgPutEvent {
@Override
public boolean choose(Set<MsgListenerEnum> msgListeners) {
return msgListeners.contains(MsgListenerEnum.UPDATE_STUDENT_INFOREMATION);
}
@Override
public void execute(ListenerMsgPutEvent listenerMsgPutEvent) {
Student student = listenerMsgPutEvent.getStudent();
try {
System.out.println(student.toString());
} catch (Exception e) {
log.error("updateStudentStategy error : {}",e);
saveFailMsg(EnumConstant.BusinessTypeEnums.UPDATE_RECORD,student,String.valueOf(student.getId()));
}
}
}
事件发布失败保存落库,后续采用定时任务扫描
package com.lyj.demo.service.pushMsg;
import com.lyj.demo.constant.EnumConstant;
import com.lyj.demo.service.NotificationLogService;
import com.lyj.demo.utils.JacksonUtil;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @author 凌兮
* @date 2020/4/27 10:36
* 抽象基类
*/
public abstract class AbstractMsgPutEvent implements MsgPutStrategy{
@Autowired
private NotificationLogService notificationLogService;
protected void saveFailMsg(EnumConstant.BusinessTypeEnums businessTypeEnum,Object content,String businessId) {
if (content == null){
return;
}
notificationLogService.saveNotificationLog(businessTypeEnum,JacksonUtil.toJson(content),
EnumConstant.NotificationLogState.FAIL.getCode(),businessId);
}
}