76

我遇到了一些 Spring bean 定义的问题。我的 main() 方法正在加载几个上下文 xml 文件,它们几乎都包含一个标签。当我的 main 方法启动时,我从 Spring 收到此错误:

Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'converterDAO' for bean class [my.package.InMemoryConverterDaoImpl] conflicts with existing, non-compatible bean definition of same name and class [my.other.package.StaticConverterDAOImpl]

两个 DAO 类都以这种方式注释:

@Repository("converterDAO")
public class StaticConverterDAOImpl implements ConverterDAO {
...
}

内存中的 dao 也有 @Repository("converterDAO") 注解。dao 在其他类中被引用,如下所示:

...
private @Autowired @Qualifier("converterDAO") ConverterDAO converterDAO;
...

我希望一个 DAO 覆盖另一个 DAO 的定义,正如我一直理解的那样,这是首先使用 DI 框架的主要原因之一。多年来,我一直在使用 xml 定义来执行此操作,并且从未遇到任何问题。但组件扫描和带注释的 bean 定义不是这样吗?Spring 说它们不“兼容”是什么意思?它们实现了相同的接口,并且它们被自动装配到该接口类型的字段中。为什么他们不兼容?

有人可以为我提供一种方法,让一个带注释的组件扫描 bean 覆盖另一个吗?

-麦克风

4

15 回答 15

45

我在使用 @RestController 的 Spring 4.x 中遇到了类似的问题。两个不同的包有一个同名的类......

package com.x.catalog

@RestController
public class TextureController {
...

package com.x.cms
@RestController
public class TextureController {
...

修复很简单...

package com.x.catalog

@RestController("CatalogTextureController")
public class TextureController {
...

package com.x.cms
@RestController("CMSTextureController")
public class TextureController {
...

问题似乎是注释被自动装配并默认采用类名。在 @RestController 注释中给它一个显式名称允许您保留类名。

于 2016-04-24T03:11:12.233 回答
39

在 XML 文件中,有一系列声明,您可以用新的定义覆盖以前的定义。使用注释时,没有beforeafter的概念。所有的豆子都处于同一水平。您定义了两个具有相同名称的 bean,而 Spring 不知道应该选择哪一个。

给它们一个不同的名称(staticConverterDAO,例如inMemoryConverterDAO),在 Spring XML 文件中创建一个别名(例如theConverterDAO),并在注入转换器时使用这个别名:

@Autowired @Qualifier("theConverterDAO")
于 2012-12-10T20:59:40.640 回答
37

我有一个类似的问题,在一个项目中有两个 jar 库(app1 和 app2)。bean "BeanName" 在 app1 中定义并在 app2 中扩展,并且重新定义了同名的 bean。

在 app1 中:

package com.foo.app1.pkg1;

@Component("BeanName")
public class Class1 { ... }

在 app2 中:

package com.foo.app2.pkg2;

@Component("BeanName")
public class Class2 extends Class1 { ... }

ConflictingBeanDefinitionException由于相同的组件 bean 名称,这会导致applicationContext 的加载异常。

为了解决这个问题,在 Spring 配置文件中applicationContext.xml

    <context:component-scan base-package="com.foo.app2.pkg2"/>
    <context:component-scan base-package="com.foo.app1.pkg1">
        <context:exclude-filter type="assignable" expression="com.foo.app1.pkg1.Class1"/>
    </context:component-scan>

因此 Class1 被排除在自动组件扫描并分配给 bean 的情况下,避免了名称冲突。

于 2014-01-30T08:46:30.947 回答
31

我遇到了类似的问题,这是因为我的一个 bean 最近被移到了另一个目录。我需要通过删除目录来进行“构建清理”,build/classes/java问题就消失了。(错误消息中有两个不同的文件路径相互冲突,尽管我知道一个实际上不应该存在了。)

于 2018-06-12T19:32:00.127 回答
12

有时,如果您移动了类并且它指的是旧类,即使它们不存在,有时也会出现问题。

在这种情况下,只需这样做:

mvn eclipse:clean

mvn eclipse:eclipse

这对我来说效果很好。

于 2019-05-03T11:27:57.040 回答
7

我遇到过同样的问题。我通过使用以下步骤解决了它(编辑:IntelliJ):

  1. 查看 -> 工具窗口 -> Maven 项目。在子窗口中打开您的项目。
  2. 单击项目旁边的箭头。
  3. 单击生命周期。
  4. 点击清洁。
于 2020-11-26T13:20:06.233 回答
2

我也有类似的问题。我再次构建了项目,问题得到了解决。

原因是,在一个文件中已经为 Annotation-specified bean 名称定义了序列。当我们对该 bean 名称进行更改并尝试运行应用程序时,Spring 无法确定选择哪一个。这就是它显示此错误的原因。

在我的例子中,我从项目中删除了以前的 bean 类,并将相同的 bean 名称添加到一个新的 bean 类中。因此 Spring 在文件中具有先前对已删除 bean 类的定义,并且在编译时与新添加的类冲突。所以如果你做一个'build clean',之前对bean类的定义将被删除并且编译会成功。

于 2018-07-12T06:08:35.987 回答
1

如果其他答案都没有解决您的问题,并且在直接或间接更改任何配置(通过 git pull/merge/rebase)后开始发生,并且您的项目是 Maven 项目:

mvn clean

希望这可以解决您的问题。或某人

于 2020-04-02T13:25:35.650 回答
1

解释内部处理此错误

您收到此错误是因为在实例化后容器试图将相同的对象分配给两个类,因为无论不同的包如何,类名都是相同的......这就是为什么错误说同名的不兼容 bean 定义..

实际上它内部的工作方式是--->>>>。

包测试1;…… @RestController 类测试{}

包测试2;…… @RestController 类测试{}

第一个容器将获得类 Test 并且 @RestController 指示它实例化为…test = new Test(); 并且它不会实例化两次在实例化容器后,将为两个类提供一个引用变量 test(与类名相同),同时它为第二个类提供测试引用,它得到不兼容的同名 bean 定义......</p>

解决办法——>>>>

为两个休息控制器分配一个参考名称,以便容器不会使用默认名称实例化并为两个类单独实例化,而不管同名

例如——>>>

包测试1;…… @RestController(“test1”) 类测试{}

包测试2;…… @RestController(“test2”) 类测试{}

注意:同样适用于@Controller、@Service、@Repository 等。

注意:如果您在类级别创建引用变量,那么您还可以使用 @Qualifier("specific refrence name") 对其进行注释,例如 @Autowired @Qualifier("test1") Test test;

于 2020-05-10T04:36:21.080 回答
1

在将现有文件移动到新包后,我在IntelliJ上遇到了同样的问题,解决了清理缓存,当尝试使用 maven 运行时遇到了该错误。我设法解决了它:

cache:clean

于 2022-01-15T13:40:59.077 回答
0

设想:

我正在开发一个多模块 Gradle 项目。

模块是:

- core, 
- service,
- geo,
- report,
- util and
- some other modules.

所以主要我们在geo模块中准备了一个 Component[ locationRecommendHttpClientBuilder ] 。

Java 代码:

import org.springframework.stereotype.Component

@Component("locationRecommendHttpClientBuilder")
class LocationRecommendHttpClientBuilder extends PanaromaHttpClientBuilder {
    @Override
    PanaromaHttpClient buildFromConfiguration() {
        this.setURL(PanaromaConf.getInstance().getString("locationrecommend.url"))
        this.setMethod(PanaromaConf.getInstance().getString("locationrecommend.method"))
        this.setProxyHost(PanaromaConf.getInstance().getString("locationrecommend.proxy.host"))
        this.setProxyPort(PanaromaConf.getInstance().getInt("locationrecommend.proxy.port", 0))
        return super.build()
    }
}

应用程序上下文.xml

<bean id="locationRecommendHttpClient"
      class="au.co.google.panaroma.platform.logic.impl.PanaromaHttpClient"
      scope="singleton" factory-bean="locationRecommendHttpClientBuilder"
      factory-method="buildFromConfiguration" />

然后决定将该组件添加到核心模块中。

一位工程师以前有地理模块的代码,然后他采用了最新的核心模块,但他忘记了采用最新的地理模块。

所以组件[ locationRecommendHttpClientBuilder ] 在他的项目中是双倍的,他得到了以下错误。

Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'LocationRecommendHttpClientBuilder' for bean class [au.co.google.app.locationrecommendation.builder.LocationRecommendHttpClientBuilder] conflicts with existing, non-compatible bean definition of same name and class [au.co.google.panaroma.platform.logic.impl.locationRecommendHttpClientBuilder]

解决程序:

geo模块中移除组件后,component[ locationRecommendHttpClientBuilder ] 仅在核心模块中可用。所以不存在冲突的情况。问题通过这种方式解决。

于 2018-05-18T08:22:33.173 回答
0

当我在工作区中导入两个项目时,我遇到了这个问题。它以某种方式创建了一个不同的 jar,因此我们可以删除 jar 和类文件并再次构建项目以获取正确的依赖关系。

于 2018-08-31T20:16:41.953 回答
0

使用 Eclipse,我已将类移动到新包中,并收到此错误。对我有用的是: 项目>清洁

并通过右键单击它并选择清理来清理我的 TomCat 服务器

感谢 Rock Lee 的回答帮助我解决了这个问题 :)

于 2020-05-05T13:29:49.410 回答
0

就我而言,问题出在 pom.xml 中,我在我的应用程序 pom.xml 中为两个不同的包添加了依赖项,这些包反映了相同的类名。

检查您的 pom.xml 或注释,它们可能是同一类的可能注入点。

于 2022-02-10T06:22:31.297 回答
-1

在 Eclipse 上刷新 gradle 项目为我解决了这个问题

于 2020-11-16T13:33:46.623 回答