Spring Boot升级后elasticsearchTemplate Bean重复定义问题求助
我来帮你分析下这个问题并给出可行的解决方案:
问题根源
Spring Boot 2.2.x版本开始,默认禁用了Bean定义覆盖(spring.main.allow-bean-definition-overriding默认值从true改为false)。而你的ExtendedESConfig继承了ESConfig,两个类都带有@Configuration注解,Spring会分别处理这两个配置类,导致elasticsearchTemplate这个Bean被两次定义,触发了启动报错。
因为你无法修改ExtendedESConfig,也不想开启Bean覆盖,我们可以从以下两个方向解决:
方案1:修改基础配置类ESConfig(如果有权限的话)
如果能协调修改ESConfig的代码,这是最优雅的解决方式。给elasticsearchTemplate的Bean方法添加@ConditionalOnMissingBean注解,让Spring只在该Bean不存在的时候才创建它:
@Configuration @EnableElasticsearchRepositories(basePackages = "subpackage-in-this-project") @PropertySource("file:path-to-file") public class ESConfig { @Bean @ConditionalOnMissingBean(name = "elasticsearchTemplate") // 添加这个注解 ElasticsearchTemplate elasticsearchTemplate(Client client) { return new ElasticsearchTemplate(client); } @Bean Client client() { // ES客户端配置 } }
这样当ExtendedESConfig(继承自ESConfig)被加载时,Spring会优先确保只创建一次elasticsearchTemplateBean,避免重复定义冲突。
方案2:在第三个项目中排除ESConfig的自动扫描
如果无法修改ESConfig和ExtendedESConfig,可以在第三个Spring Boot项目的启动类中,通过注解规则让Spring不加载ESConfig:
方式A:使用@SpringBootApplication直接排除
@SpringBootApplication(exclude = ESConfig.class) public class ThirdProjectApplication { public static void main(String[] args) { SpringApplication.run(ThirdProjectApplication.class, args); } }
方式B:使用@ComponentScan自定义过滤规则
如果项目中自定义了@ComponentScan范围,可以添加排除规则:
@SpringBootApplication @ComponentScan( basePackages = "your.third.project.packages", excludeFilters = @ComponentScan.Filter( type = FilterType.ASSIGNABLE_TYPE, classes = ESConfig.class ) ) public class ThirdProjectApplication { public static void main(String[] args) { SpringApplication.run(ThirdProjectApplication.class, args); } }
这样Spring只会处理ExtendedESConfig,只会创建一个elasticsearchTemplateBean,彻底解决重复定义的问题。
补充说明
为什么升级前没问题?因为Spring Boot 2.0.x版本中spring.main.allow-bean-definition-overriding默认是true,子类的Bean会自动覆盖父类的,所以不会报错;升级到2.2.x后默认禁用了覆盖机制,这个隐藏的重复定义问题就暴露出来了。
内容的提问来源于stack exchange,提问作者improbable

