注释指定的bean名称与现有的,不兼容的bean def冲突

时间:2012-12-10 12:52:18

标签: spring repository

我遇到了一些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定义却不是这样吗?春天的意思是什么,当它说它们不兼容时#34 ;?它们实现相同的接口,并且它们被自动装配到该接口类型的字段中。为什么他们不相容?

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

-Mike

13 个答案:

答案 0 :(得分:31)

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

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

@Autowired @Qualifier("theConverterDAO")

答案 1 :(得分:29)

我遇到了类似的问题,在一个项目中有两个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 { ... }

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

要解决此问题,请在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,避免名称冲突。

答案 2 :(得分:23)

我使用@RestController与Spring 4.x有类似的问题。两个不同的包有一个同名的类......

var data = "";
//show loading
//block all input
abc.abc(lat, long).then(function(x) {
    data = x;
    console.log(data);
    // hide loading
    // continue the process
});
console.log(data);

修复很容易......

package com.x.catalog

@RestController
public class TextureController {
...

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

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

答案 3 :(得分:7)

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

答案 4 :(得分:0)

方案:

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

模块是:

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

因此,我们主要在 geo 模块中准备了一个组件[ 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()
    }
}

应用context.xml中

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

然后决定在核心模块中添加此组件。

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

因此组件[ 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 模块中删除组件后,组件[ locationRecommendHttpClientBuilder ]仅在核心模块中可用。所以没有冲突的情况。通过这种方式解决问题。

答案 5 :(得分:0)

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

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

就我而言,我从项目中删除了先前的bean类,并将相同的bean名称添加到了新的bean类中。因此,Spring对文件中已删除的Bean类具有先前的定义,并且在编译时与新添加的类冲突。因此,如果您进行“内部清理”,则将删除先前对Bean类的定义,并且编译将成功。

答案 6 :(得分:0)

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

答案 7 :(得分:0)

有时候,如果您移动了类并且它引用了旧类,即使它们不存在,也会出现此问题。

在这种情况下,只需执行以下操作:

mvn eclipse:clean

mvn eclipse:eclipse

这对我来说很好。

答案 8 :(得分:0)

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

mvn clean

希望这可以解决您的问题。还是有人

答案 9 :(得分:0)

使用Eclipse,我已经将类移到了新软件包中,并且出现了此错误。对我有用的是在做: 项目>清理

并通过右键单击它并选择 clean

来清洁我的TomCat服务器。

感谢李洛克(Rock Lee)的回答,帮助我弄清楚了:)

答案 10 :(得分:0)

解释内部针对此错误

您会收到此错误,因为在实例化之后,容器尝试将相同的对象分配给两个类,因为类名是相同的,而与不同的包无关,这就是为什么错误表示不兼容的同名bean定义。

实际上,它是如何在内部工作的--- >>>>。

pkg test1; …。 @RestController 测试类{}

pkg test2; …。 @RestController 测试类{}

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

解决方案— >>>>

为两个rest控制器分配一个引用名称,这样容器就不会使用默认名称实例化,并且对于这两个类而言,都不会高效地实例化 同名

例如->>>

pkg test1; …。 @RestController(“ test1”) 测试类{}

pkg test2; …。 @RestController(“ test2”) 测试类{}

注意:@ Controller,@ Service,@ Repository等也可以使用。

注意:如果要在类级别创建参考变量,则还可以使用@Qualifier(“特定参考名称”)进行注释。 @Autowired @Qualifier(“ test1”) 测试测试;

答案 11 :(得分:0)

我有同样的问题。我通过以下步骤解决了此问题(编辑器: IntelliJ ):

  1. 视图->工具窗口-> Maven项目。在打开您的项目 子窗口。
  2. 单击项目旁边的箭头。
  3. 单击生命周期。
  4. 单击干净。

答案 12 :(得分:-1)

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