ContextRefreshedEvent事件引发的一些问题
最近在项目中遇见一个乌龙,在springboot中执行test方法,导致测试结果跟预期结果始终不一致,通过排查,发现是test执行的时候,数据自动发生了变化.
后期跟踪,发现问题的所在:test方法执行会是的spring容器重新加载,spring容器加载完毕,触发ContextRefreshedEvent事件,导致写的监听事件执行,导致数据出错.也是自己粗心,日志打印不全面,导致找了很久错误.
@EventListener(classes = {
ContextRefreshedEvent.class,
UserCheckPendingEvent.class})
public void saveUserCheckPendingStatistics(ApplicationContextEvent applicationContextEvent) {
// Root 容器刷新才触发
boolean refreshFlag = ApplicationContextProvider.isRootContextRefreshEvent(applicationContextEvent);
if (!refreshFlag && applicationContextEvent instanceof UserCheckPendingEvent) {
refreshFlag = true;
}
if (refreshFlag) {
log.info("执行统计用户待审核数据方法");
long startTime = System.currentTimeMillis();
Integer count = userModifyRecordDao.countUserCheckPending();
redisDao.hset(RedisConstants.CHECK_PENDING, RedisConstants.CHECK_PENDING_USER, count);
log.info("统计用户待审核数据方法执行结束,用时:{}毫秒", System.currentTimeMillis() - startTime);
}
}
ContextRefreshedEvent.class在spring容器重载后监听执行.
同时,想自定义启动监听事件,可以自定义一个事件,继承ApplicationContextEvent
@Getter
@ToString
public class VideoBrowseMQMessageEvent extends AbstractMQMessageEvent {
private TbRecommendUserWatchRecord watchRecord;
public VideoBrowseMQMessageEvent(ApplicationContext source, TbRecommendUserWatchRecord watchRecord) {
super(source);
this.watchRecord = watchRecord;
}
}
然后写一个类,实现ApplicationContextAware方法,构造注入
通过new 监听事件,通过ApplicationContext发布事件,还可以携带自定义参数
@Component
public class VideoSender implements ApplicationContextAware {
private ApplicationContext ctx;
@Override
public void setApplicationContext(ApplicationContext ctx) {
this.ctx = ctx;
}
/**
* 发布视频浏览事件
*/
public void videoBrowseSend(TbRecommendUserWatchRecord watchRecord) {
if (watchRecord == null) {
throw new NullPointerException();
}
VideoBrowseMQMessageEvent mse = new VideoBrowseMQMessageEvent(this.ctx, watchRecord);
ctx.publishEvent(mse);
}
记录是为了防止再犯此类错误.后期还需深入了解