ISSUE
错误分析
DeferredApplicationEventPublisher的继承关系
1 | import org.springframework.context.ApplicationContext; |
DeferredApplicationEventPublisher的依赖图

现在来分析具体出现NPE错误的原因
先看EventPublishingConfigService中的addListener
1 |
|
然后看DelegatingEventPublishingListener代码的继承关系
1 | import com.alibaba.nacos.api.config.ConfigService; |
可以看到,在创建DelegatingEventPublishingListener对象的时候,会传入一个线程池Executor,以及一个ApplicationEventPublisher(其实就是DeferredApplicationEventPublisher)
然后再看看CacheData.safeNotifyListener()方法做了什么操作
1 | private void safeNotifyListener(final String dataId, final String group, final String content, final String md5, final ManagerListenerWrap listenerWrap) { |
这里看到,safeNotifyListener是将事件广播给所有的Listener,然后有一段及其重要的代码段,它就是导致LinkedList出现并发使用的原因
1 | listener.getExecutor().execute(job); |
这里还记得刚刚说过的DelegatingEventPublishingListener对象在创建之初有传入Executor参数吗?这里Listener调用Executor将上述的任务调入线程池中进行调度,因此,导致了DeferredApplicationEventPublisher可能存在并发的使用
错误复现
1 | public class DeferrNPE { |
最终修正
由于是非线程安全使用在并发的场景下,因此只能更改上层nacos-spring-context的容器使用,将原先的非线程安全的LinkedList转为线程安全的ConcurrentLinkedQueue