Spring Boot 应用程序“bean 类的 bean 名称与现有冲突” - 如何从 3rd 方库/依赖项中排除包/类?

问题描述 投票:0回答:2

我有一个 Spring Boot 应用程序,最近从 1.x.x 迁移到 2.x.x。我正在使用一些第 3 方库/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?请记住,这些是 3rd 方库,我无法编辑

我正在包含 main 方法的 Java 类上使用

@SpringBootApplication

java spring spring-boot applicationcontext spring-bean
2个回答
0
投票

首先,应用程序中有两个类

PrometheusServletAutoConfiguration
是一种代码味道,我首先会问自己为什么有两个类。理想的解决方案是拥有一个。

至于Spring异常,可能是因为Spring自动检测到两个带有

@Configuration
注释的类,并生成两个同名的bean(默认情况下,bean名称是根据类名称计算的)。您可以覆盖其中一个类的 bean 名称:

@Configuration("myPrometheusServletAutoConfig")
public class PrometheusServletAutoConfiguration {

相关:注释指定的 bean 名称与现有的、不兼容的 bean def 冲突


0
投票

这应该是一条评论,但对于这样的评论来说太长了。

我还没有测试过这个(如果它不起作用,我会删除这个答案),但是你可以尝试吗?你可以做

// 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();
}

然后运行您的应用程序。

© www.soinside.com 2019 - 2024. All rights reserved.