源码解析来看spring.main.allow-bean-definition-overriding=true配置nacos中不生效问题

报错信息

springboot项目启动报错:Error starting ApplicationContext. To display the conditions report re-run your application with ‘debug’ enabled.
2022-03-28 16:55:30.412 ERROR 10564 — [ main] o.s.b.d.LoggingFailureAnalysisReporter :


APPLICATION FAILED TO START


Description:

The bean ‘redisTemplate’, defined in class path resource [com/uhu/redis/config/RedisConfig.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/boot/autoconfigure/data/redis/RedisAutoConfiguration.class] and overriding is disabled.

Action:

Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

出错分析

我们有很多应用程序依赖于覆盖现有 Spring bean 的模块。升级到 spring-boot 2.1.0 后,应用程序无法再启动,因为 spring.main.allow-bean-definition-overriding=true 必须设置。

默认情况下,单个配置文件中存在id或者name相同的bean定义,spring解析时会报错;不同配置文件中存在id或者name相同的bean定义,后面加载的bean定义会覆盖前面的bean定义

springboot启动,默认allow-bean-definition-overriding为false,我们需要修改为true。
源码解析来看spring.main.allow-bean-definition-overriding=true配置nacos中不生效问题_第1张图片
加载redisTemplate时候发现已存在相同名称的bean,查看allow-bean-definition-overriding=false,故抛出异常。
源码解析来看spring.main.allow-bean-definition-overriding=true配置nacos中不生效问题_第2张图片
我们项目使用的nacos配置中心,发现将spring.main.allow-bean-definition-overriding=true配置到nacos中,系统启动还是报错,而配置到bootstrap.yml或者application.yml中则程序正常启动。

跟随springboot启动流程,首先启动加载spring的配置环境及springcloud的环境,这里主要是我们的bootstrap.yml。
源码解析来看spring.main.allow-bean-definition-overriding=true配置nacos中不生效问题_第3张图片
准备上下文的时候,设置allow-bean-definition-overriding,此时值=false
源码解析来看spring.main.allow-bean-definition-overriding=true配置nacos中不生效问题_第4张图片

可以看到allowBeanDefinitionOverriding默认为false。
nacos读取配置后没有刷新该值,故只能配置在application.yml或者bootstrap.yml中,交由spring初始化加载。
源码解析来看spring.main.allow-bean-definition-overriding=true配置nacos中不生效问题_第5张图片

解决方案

1.配置到bootstrap.yml或者application.yml中
2.实现EnvironmentPostProcessor并设置值,并在META-INF中注入我们的类
org.springframework.boot.env.EnvironmentPostProcessor=package.name.YourClassname

@Override
  public void postProcessEnvironment(final ConfigurableEnvironment environment, final SpringApplication application) {
    application.setAllowBeanDefinitionOverriding(true);
  }

源码解析来看spring.main.allow-bean-definition-overriding=true配置nacos中不生效问题_第6张图片

再次debugger可以看到allowBeanDefinitionOverriding=true
源码解析来看spring.main.allow-bean-definition-overriding=true配置nacos中不生效问题_第7张图片

你可能感兴趣的:(Java,SpringCloud,Spring源码,elasticsearch,搜索引擎,linux)