Spring Boot 应用程序“bean 类的 bean 名称与现有冲突” - 如何从 3rd 方库/依赖项中排除包/类?
Posted
技术标签:
【中文标题】Spring Boot 应用程序“bean 类的 bean 名称与现有冲突” - 如何从 3rd 方库/依赖项中排除包/类?【英文标题】:Spring Boot app "bean name for bean class conflicts with existing" - how to exclude package/Class from 3rd party library/dependency? 【发布时间】:2021-05-19 19:55:33 【问题描述】:我有一个最近从 1.x.x 迁移到 2.x.x 的 Spring Boot 应用程序。我正在使用一些 3rd 方库/JAR 来使用 Prometheus 记录一些指标。
问题是我有 (2) 个名为 PrometheusServletAutoConfiguration
的 Java 类,它们都用 @Configuration
注释,我得到了臭名昭著的 Spring 异常:
org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'prometheusServletAutoConfiguration' for bean class [com.my.package.path1.PrometheusServletAutoConfiguration] conflicts with existing, non-compatible bean definition of same name and class [com.my.package.path2.PrometheusServletAutoConfiguration]
如您所见,它们的 FQDN 确实略有不同(完全限定的域名,或包路径,我为本示例简化了它,如您所见),但主类名称相同,所以我认为 Spring 正在尝试找出要创建和失败的 Bean。这完全让我感到困惑,我在 IntelliJ 中使用 Spring 1.x.x 查看了旧分支代码中的代码/库,并且 从未抛出此异常(它在 Spring 1.x.x 中是否被忽略了? ?)。我还会注意到代码编译良好,但在运行时失败(有道理)
这里是最好的分辨率吗?我是否应该告诉 Spring 不要扫描这些类 FQDN 之一,以便它只在应用程序上下文中创建 1 个 bean?请记住,这些是第 3 方库,我无法编辑。
我在包含 main 方法的 Java 类上使用 @SpringBootApplication
。
【问题讨论】:
这是一个有趣的问题,很遗憾你没有回来说我的回答是否对你有用。 【参考方案1】:首先,在应用程序中有两个类PrometheusServletAutoConfiguration
是一种代码味道,我会首先问自己为什么有两个类。理想的解决方案是拥有一个。
至于Spring的异常,可能是因为Spring自动检测到了@Configuration
注解的两个类,生成了两个同名的bean(默认bean的名字是根据类名计算出来的)。您可以覆盖其中一个类的 bean 名称:
@Configuration("myPrometheusServletAutoConfig")
public class PrometheusServletAutoConfiguration
相关:Annotation-specified bean name conflicts with existing, non-compatible bean def
【讨论】:
@M A 这是一个遗留应用程序,两个名称冲突的类是依赖项——如果它是一个外部 JAR 被拉入我的项目,我真的可以覆盖它吗? @ennth 你真的需要两者吗?如果没有,您可以排除其中之一:***.com/questions/44255224/…【参考方案2】:这应该是一个评论,但它太长了。
我没有测试过这个(如果它不起作用,我会删除这个答案),但是你可以试试吗?你可以这样做
// extend one of the configs
@Configuration(value = "myPrometheusServletAutoConfig")
public class CopyConfig extends com.my.package.path2.PrometheusServletAutoConfiguration
然后定义一个BeanPostProcessor
:
public class MyPostProcessor implements BeanPostProcessor
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
if(bean.getClass().equals(com.my.package.path2.PrometheusServletAutoConfiguration.class))
return new CopyConfig();
return bean;
并在你的上下文中注册这个:
@Bean
public MyPostProcessor customBeanFactory()
return new MyPostProcessor();
然后运行您的应用程序。
【讨论】:
以上是关于Spring Boot 应用程序“bean 类的 bean 名称与现有冲突” - 如何从 3rd 方库/依赖项中排除包/类?的主要内容,如果未能解决你的问题,请参考以下文章