当前位置:首页 > 服务端 > 配置变更导致ConfigurationProperties配置List集合遍历出现NullPointerException

配置变更导致ConfigurationProperties配置List集合遍历出现NullPointerException

背景

在Configuration配置类中声明了一个配置bean,如下:

配置变更导致ConfigurationProperties配置List集合遍历出现NullPointerException _ JavaClub全栈架构师技术笔记

  

 配置类中存在集合配置

配置变更导致ConfigurationProperties配置List集合遍历出现NullPointerException _ JavaClub全栈架构师技术笔记

 

 

对应在Apollo中的配置如下

配置变更导致ConfigurationProperties配置List集合遍历出现NullPointerException _ JavaClub全栈架构师技术笔记

 

 

 

使用时,注入 AccessControlConfigBean, 具体使用方式如下:

配置变更导致ConfigurationProperties配置List集合遍历出现NullPointerException _ JavaClub全栈架构师技术笔记

 

 

 

我在监听到Apollo配置变更时,发布了一个 EnvironmentChangeEvent 事件,如下:

配置变更导致ConfigurationProperties配置List集合遍历出现NullPointerException _ JavaClub全栈架构师技术笔记

 

 

 

问题描述

问题一:当apollo中该项目的任意配置变更时,上述用红色圈出来的match会有小概率出现为null的情况,从而导致空指针。

问题二:于是我加了一个判断,当遍历元素是null时,跳过处理配置变更导致ConfigurationProperties配置List集合遍历出现NullPointerException _ JavaClub全栈架构师技术笔记

 

 

 

 此时,出现了另一个问题,97行报了NullPointerException, 如下:

配置变更导致ConfigurationProperties配置List集合遍历出现NullPointerException _ JavaClub全栈架构师技术笔记

 

 

 

问题剖析

问题一:为什么变更配置会导致出现元素为null?

根据问题出现的场景,可以断定spring在处理EnvironmentChangeEvent事件,刷新bean配置时存在问题,我们找到这个事件的处理逻辑

配置变更导致ConfigurationProperties配置List集合遍历出现NullPointerException _ JavaClub全栈架构师技术笔记

 

 

 

配置变更导致ConfigurationProperties配置List集合遍历出现NullPointerException _ JavaClub全栈架构师技术笔记

 

 

配置变更导致ConfigurationProperties配置List集合遍历出现NullPointerException _ JavaClub全栈架构师技术笔记

 

 

 

可以看到配置Bean的刷新过程,就是将Bean进行destroy后,再重新init。

destroy的逻辑就是注销了一些监听器,以及调用了声明的destroy方法,并不会去清除bean里面的字段,所以问题不在destroy逻辑中。

init的逻辑是调用了bean的aware方法,并执行了BeanPostProcessor的扩展处理,配置刷新就是在这里完成的,相关类是:ConfigurationPropertiesBindingPostProcessor

最终完成字段值更新是在JavaBeanBinder这个类中。

配置变更导致ConfigurationProperties配置List集合遍历出现NullPointerException _ JavaClub全栈架构师技术笔记

 配置变更导致ConfigurationProperties配置List集合遍历出现NullPointerException _ JavaClub全栈架构师技术笔记

 

 对于配置类中的集合(Collection/List/Set)字段, 这边会调用 CollectionBinder 的merge方法

可以看到,原先的集合对象并不是被直接替换,而是先进行了 clear,再往里面addAll

至此,真相大白,由于这两部操作的非原子性,如果在这个期间,此集合正在被遍历或者使用,就会出现开头的异常,这本质上是属于线程安全问题。

 

解决方案

方案1:在使用集合时,new一个新的集合,如下:

配置变更导致ConfigurationProperties配置List集合遍历出现NullPointerException _ JavaClub全栈架构师技术笔记

 

 

方案2:在配置类中,将List的实现类修改为 CopyOnWriteArrayList, 如下:

配置变更导致ConfigurationProperties配置List集合遍历出现NullPointerException _ JavaClub全栈架构师技术笔记

 

作者:EEEEET
来源链接:https://www.cnblogs.com/imyjy/p/16306778.html

版权声明:
1、Java侠(https://www.javaxia.com)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。





本文链接:https://www.javaxia.com/server/125660.html

分享给朋友:

“配置变更导致ConfigurationProperties配置List集合遍历出现NullPointerException” 的相关文章