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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13801359/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:35:25  来源:igfitidea点击:

Annotation-specified bean name conflicts with existing, non-compatible bean def

springrepository

提问by user1283068

I'm having a problem with some Spring bean definitions. I have a couple of context xml files that are being loaded by my main() method, and both of them contain almost exclusively a tag. When my main method starts up, I get this error from Spring:

我有一些 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]

Both DAO classes are annotated this way:

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

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

The in-memory dao also has the @Repository("converterDAO") annotation. The dao is referenced in other classes like this:

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

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

I want one DAO to override the definition of the other one, which as I always understood it was one of the principal reasons to use a DI framework in the first place. I've been doing this with xml definitions for years and never had any problems. But not so with component scans and annotated bean definitions? And what does Spring mean when it says they are not "compatible"? They implement the same interface, and they are autowired into fields that are of that interface type. Why the heck are they not compatible?

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

Can someone provide me with a way for one annotated, component-scanned bean to override another?

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

-Mike

-麦克风

采纳答案by JB Nizet

In an XML file, there is a sequence of declarations, and you may override a previous definition with a newer one. When you use annotations, there is no notion of beforeor after. All the beans are at the same level. You defined two beans with the same name, and Spring doesn't know which one it should choose.

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

Give them a different name (staticConverterDAO, inMemoryConverterDAOfor example), create an alias in the Spring XML file (theConverterDAOfor example), and use this alias when injecting the converter:

给他们一个不同的名称(staticConverterDAOinMemoryConverterDAO为例),创建Spring的XML文件(别名theConverterDAO注入器时为例),并使用此别名:

@Autowired @Qualifier("theConverterDAO")

回答by user1897261

I had a similar problem, with two jar libraries (app1 and app2) in one project. The bean "BeanName" is defined in app1 and is extended in app2 and the bean redefined with the same name.

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

In app1:

在应用程序 1 中:

package com.foo.app1.pkg1;

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

In app2:

在应用程序 2 中:

package com.foo.app2.pkg2;

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

This causes the ConflictingBeanDefinitionExceptionexception in the loading of the applicationContext due to the same component bean name.

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

To solve this problem, in the Spring configuration file applicationContext.xml:

为了解决这个问题,在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>

So the Class1 is excluded to be automatically component-scanned and assigned to a bean, avoiding the name conflict.

因此 Class1 被排除在自动组件扫描之外并分配给 bean,避免名称冲突。

回答by Ian Newland

I had a similar issue with Spring 4.x using @RestController. Two different packages had a class with the same name...

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

package com.x.catalog

@RestController
public class TextureController {
...

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

The fix was easy...

修复很容易...

package com.x.catalog

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

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

The problem seems to be that the annotation gets autowired and takes the class name by default. Giving it an explicit name in the @RestController annotation allows you to keep the class names.

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

回答by Rock Lee

I had a similar problem, and it was because one of my beans had been moved to another directory recently. I needed to do a "build clean" by deleting the build/classes/javadirectory and the problem went away. (The error message had the two different file paths conflicting with each other, although I knew one should not actually exist anymore.)

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

回答by Snehal Masne

Sometimes the problem occurs if you have moved your classes around and it refers to old classes, even if they don't exist.

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

In this case, just do this :

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

mvn eclipse:clean

mvn eclipse:eclipse

This worked well for me.

这对我来说效果很好。

回答by NShani

I also had a similar problem. I built the project again and the issue was resolved.

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

The reason is, there are already defined sequences for the Annotation-specified bean names, in a file. When we do a change on that bean name and try to run the application Spring cannot identify which one to pick. That is why it shows this error.

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

In my case, I removed the previous bean class from the project and added the same bean name to a new bean class. So Spring has the previous definition for the removed bean class in a file and that conflicts with the newly added class while compiling. So if you do a 'build clean', previous definitions for bean classes will be removed and compilation will success.

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

回答by Roopal

I faced this issue when I imported a two project in the workspace. It created a different jar somehow so we can delete the jars and the class files and build the project again to get the dependencies right.

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

回答by Jo?o Rodrigues

If none of the other answers fix your problem and it started occurring after change any configuration direct or indirectly (via git pull / merge / rebase) and your project is a Maven project:

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

mvn clean

Hope this fixes your problem. Or someones

希望这能解决您的问题。或者某人

回答by pinkninja

Using Eclipse, I had moved classes into new packages, and was getting this error. What worked for me was doing: Project > Clean

使用 Eclipse,我将类移到了新的包中,并且出现了这个错误。对我有用的是: 项目>清洁

and also cleaning my TomCat server by right-clicking on it and selecting clean

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

Thanks to Rock Lee's answer for helping me figure it out :)

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

回答by abhinav kumar

Explanation internal working on this error

解释内部处理此错误

You are getting this error because after instantiation the container is trying to assign same object to both classes as class name is same irrespective of different packages......thats why error says non compatible bean definition of same name ..

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

Actually how it works internally is--->>>>.

实际上它内部的工作原理是--->>>>。

pkg test1; …. @RestController class Test{}

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

pkg test2; …. @RestController class Test{}

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

First container will get class Test and @RestController indicates it to instantiate as…test = new Test(); and it won't instantiate twice After instantiating container will provide a reference variable test(same as class name) to both the classes and while it provide test reference To second class it gets non compatible bean definition of same name ……

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

Solution—>>>>

解决方案——>>>>

Assign a refrence name to both rest controller so that container won't instantiate with default name and instantiate saperately for both classes irrespective Of same name

为两个休息控制器分配一个引用名称,以便容器不会使用默认名称实例化并为两个类分别实例化,而不管名称是否相同

For example——>>>

例如——>>>

pkg test1; …. @RestController(“test1”)class Test{}

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

pkg test2; …. @RestController(“test2”)class Test{}

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

Note:The same will work with @Controller,@Service,@Repository etc..

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

Note: if you are creating reference variable at class level then you can also annotate it with @Qualifier("specific refrence name") for example @Autowired @Qualifier("test1") Test test;

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