当前位置: 首页 > 后端技术 > Java

@RefreshScope可以随便用吗?

时间:2023-04-02 00:23:49 Java

最近在使用COLA框架自带的异步任务时,发现每次执行异步任务都会执行两次。有些接口如果不幂等就会出现问题,比如进入Library操作之类的会导致数据重复存储,造成严重的bug。带着疑惑,我开始了bug之旅。1问题发现1.首先查看执行入口。有两个吗?只找到一个;2.调用入口的问题?通过controller直接调用handler,或者调用两次。3、简化代码,把handler里的内容全部删掉,只有一个logger打印语句?结果还是打印了两次。但是这次,我发现logger的线程名不一样了,是两个线程。2021-07-2614:11:19.429INFO47294---[pool-4-thread-2]c.e.colademo.event.handler.TestHandler:>>>>>>>>>>>>>>02021-07-2614:11:19.430INFO47294---[pool-4-thread-1]c.e.colademo.event.handler.TestHandler:>>>>>>>>>>>>>>02故障排除为什么有两个并发执行的线程呢?查看可乐源代码。publicvoidasyncFire(EventIevent){this.eventHub.getEventHandler(event.getClass()).parallelStream().map((p)->{Responseresponse=null;try{if(null!=p.getExecutor()){p.getExecutor().submit(()->{returnp.execute(event);});}else{this.defaultExecutor.submit(()->{returnp.execute(event);});}}catch(Exceptionvar5){response=this.handleException(p,response,var5);}returnresponse;}).collect(Collectors.toList());}提交异步任务,最终转到上面的代码,将任务提交到线程池中执行。如果没有自定义线程池,则会提交到defaultExecutor的默认线程池。发现提交了两次,查看这个对象的内容,==发现Event对象和Handler对象都有两个==。3.问题的原因是什么?这个对象和之前的handler对象相比,唯一的区别就是使用了@RefreshScope,查看注解源码,发现使用==这个注解的对象会使用代码创建一个新的对象,并缓存起来==,调试源码,查看缓存对象。发现确实有一个TestHandler对象,对象是@12349。与图1中的handler对象相比,多了一个TestHandler对象,也是@12349。原来是因为使用了注解@RefreshScope,这个注解会创建一个对象,这样就会出现两个一模一样的对象,导致重复执行。结论:使用注解@RefreshScope时,需要注意。获取到的配置内容最好放在单独的属性对象中,不要和其他代码混在一起。