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

我对一些 Spring bean 的定义有疑问。我有两个用 main ()方法加载的 context 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”)注释:

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

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

有没有人能提供一种方法,让一个带注释的组件扫描 bean 覆盖另一个?

210615 次浏览

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 before or 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.

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

@Autowired @Qualifier("theConverterDAO")

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.

In app1:

package com.foo.app1.pkg1;


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

In app2:

package com.foo.app2.pkg2;


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

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

To solve this problem, in the Spring configuration file 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.

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

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.

Scenario:

I am working on a multi-module Gradle project.

Modules are:

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

So primarily we have prepared a Component[locationRecommendHttpClientBuilder] in geo module.

Java Code:

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

application-context.xml

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

Then it is decided to add this component in core module.

One engineer has previous code for geo module and then he has taken the latest module of core but he forgot to take the latest geo module.

So the component[locationRecommendHttpClientBuilder] is double times in his project and he was getting the following error.

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]

Solution Procedure:

After removal the component from geo module, component[locationRecommendHttpClientBuilder] is only available in core module. So there is no conflicting situation. Issue is solved by this way.

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/java directory 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.)

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.

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.

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.

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.

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:

mvn clean

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

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

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 ..

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

pkg test1; …. @RestController class Test{}

pkg test2; …. @RestController class Test{}

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 ……

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{}

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

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

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;

Refresh gradle project on Eclipse solved this problem for me

I had the same issue. I solved it by using the following steps(Editor: IntelliJ):

  1. View -> Tool Windows -> Maven Project. Opens your projects in a sub-window.
  2. Click on the arrow next to your project.
  3. Click on the lifecycle.
  4. Click on clean.

I had the same issue on IntelliJ after moving an existing file to a new package, solved cleaning caché, when trying to run with maven got that error. I managed solve it with:

cache:clean

In my case, issue was with pom.xml I had dependency added in my application pom.xml for two different packages, which were reflecting to same class name.

Check your pom.xml or annotations which can be the possible injection point for same class.

if you build server with file jar and you use mvn clean install then you change branch with git you have to use command mvn clean either it throw exception as on the article. key word: mvn clean