关于java:RefreshScope能随便用嘛

最近在应用COLA框架自带的异步工作时,发现每次执行异步都执行了两次,如果一些没有做幂等的接口,这样是会有问题的,比方入库操作之类的,就会造成数据反复入库,造成重大bug。

带着纳闷,开始了 bug 之旅。

1 问题发现

1、首先排查执行入口,是不是有两个,发现只有一个;

2、调用入口的问题?间接通过controller调用handler,还是调用了两次。

3、简化代码,把handler内的内容都删掉,只有一个logger打印语句?后果还是打印了两次。

然而这次,发现logger的线程名不一样,是两个线程。

2021-07-26 14:11:19.429  INFO 47294 --- [pool-4-thread-2] c.e.colademo.event.handler.TestHandler   : >>>>>>>>>>>>> 0
2021-07-26 14:11:19.430  INFO 47294 --- [pool-4-thread-1] c.e.colademo.event.handler.TestHandler   : >>>>>>>>>>>>> 0

2 问题排查

为什么会有两个线程同时执行呢?查看COLA源码。

public void asyncFire(EventI event) {
    this.eventHub.getEventHandler(event.getClass()).parallelStream().map((p) -> {
        Response response = null;

        try {
            if (null != p.getExecutor()) {
                p.getExecutor().submit(() -> {
                    return p.execute(event);
                });
            } else {
                this.defaultExecutor.submit(() -> {
                    return p.execute(event);
                });
            }
        } catch (Exception var5) {
            response = this.handleException(p, response, var5);
        }

        return response;
    }).collect(Collectors.toList());
}

提交异步工作,最终都走到下面的代码,将工作提交到线程池执行,如果没有自定义线程池,那么会提交到defaultExecutor 这个默认线程池中。

发现提交了两遍,查看this对象中的内容,==发现Event对象和Handler对象都有两个==。

3 问题起因

是什么起因会造成反复对象呢?

比照之前的handler对象,这个对象惟一的不同就是应用@RefreshScope,查看注解源码,发现应用了==这个注解的对象,都会应用代码创立一个新的对象,并缓存起来==,debug源码,查看缓存的对象。

发现确实有TestHandler对象,对象为@12349。

比照图1中的handler对象,外面也有一个TestHandler对象,对象也是@12349.

原来如此,因为应用了注解@RefreshScope,这个注解会创立一个对象,这样就会有两个雷同的对象,造成反复执行。

论断:应用注解@RefreshScope须要留神,最好把获取配置的内容放在独自的property对象中,不要和其余代码混用。

【腾讯云】云产品限时秒杀,爆款1核2G云服务器,首年50元

阿里云限时活动-2核2G-5M带宽-60G SSD-1000G月流量 ,特惠价99元/年(原价1234.2元/年,可以直接买3年),速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

You may also like...

发表评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据