Аннотирование bean имя конфликтует с существующим, несовместимым bean def
У меня проблема с некоторыми определениями Spring bean. У меня есть несколько 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 переопределял определение другого, что, как я всегда понимал, это была одна из основных причин использования основы DI. Я делал это с определениями xml в течение многих лет и никогда не испытывал никаких проблем. Но не так с помощью компонентного сканирования и аннотированных определений bean? И что означает Spring, когда говорится, что они не "совместимы"? Они реализуют один и тот же интерфейс, и они автоматически добавляются в поля этого типа интерфейса. Почему они не совместимы?
Может ли кто-нибудь предоставить мне способ для одного аннотированного, компонентного сканирования bean переопределить другой?
-Mike
Ответы
Ответ 1
В XML файле существует последовательность объявлений, и вы можете переопределить предыдущее определение с более новым. Когда вы используете аннотации, нет понятия до или после. Все beans находятся на одном уровне. Вы определили два beans с тем же именем, а Spring не знает, какой из них выбрать.
Дайте им другое имя (например, staticConverterDAO, inMemoryConverterDAO), создайте псевдоним в XML файле Spring (например, ConverterDAO) и используйте этот псевдоним при инъекции конвертера:
@Autowired @Qualifier("theConverterDAO")
Ответ 2
У меня была аналогичная проблема с двумя библиотеками jar (app1 и app2) в одном проекте. определено в приложении 1 и расширено в app2 и bean переопределено с тем же именем.
В приложении 1:
package com.foo.app1.pkg1;
@Component("BeanName")
public class Class1 { ... }
В app2:
package com.foo.app2.pkg2;
@Component("BeanName")
public class Class2 extends Class1 { ... }
Это вызывает исключение ConflictingBeanDefinitionException
при загрузке applicationContext из-за того же имени компонента bean.
Чтобы решить эту проблему, в файле конфигурации 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, избегая конфликта имен.
Ответ 3
У меня была аналогичная проблема с Spring 4.x с помощью @RestController. У двух разных пакетов был класс с тем же именем...
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 позволяет сохранить имена классов.
Ответ 4
У меня была похожая проблема, и это было потому, что один из моих bean-компонентов был недавно перемещен в другой каталог. Мне нужно было выполнить "чистую сборку", удалив каталог build/classes/java
и проблема исчезла. (В сообщении об ошибке два разных пути к файлам конфликтовали друг с другом, хотя я знал, что один не должен больше существовать.)
Ответ 5
Сценарий:
Я работаю над многомодульным проектом Gradle.
Модули это:
- core,
- service,
- geo,
- report,
- util and
- some other modules.
Итак, в первую очередь мы подготовили Компонент [ 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" />
Затем решено добавить этот компонент в основной модуль.
У одного инженера был предыдущий код для геомодуля, а затем он взял последний модуль ядра, но забыл взять последний геомодуль.
Так что компонент [ 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]
Процедура решения:
После удаления компонента из геомодуля компонент [ locationRecommendHttpClientBuilder ] доступен только в основном модуле. Так что нет конфликтной ситуации. Проблема решена этим способом.
Ответ 6
У меня тоже была похожая проблема. Я построил проект снова, и проблема была решена.
Причина в том, что в файле уже определены последовательности для имен компонентов, указанных в аннотации. Когда мы вносим изменения в это имя бина и пытаемся запустить приложение, Spring не может определить, какое из них выбрать. Вот почему он показывает эту ошибку.
В моем случае я удалил предыдущий класс компонента из проекта и добавил то же имя компонента в новый класс компонента. Таким образом, Spring имеет предыдущее определение для удаленного класса bean-компонента в файле, и это конфликтует с вновь добавленным классом во время компиляции. Поэтому, если вы выполните 'build clean', предыдущие определения классов bean-компонентов будут удалены, и компиляция будет успешной.
Ответ 7
Я столкнулся с этой проблемой, когда импортировал два проекта в рабочую область. Он каким-то образом создал другой jar файл, поэтому мы можем удалить jar файлы и файлы классов и собрать проект заново, чтобы получить правильные зависимости.
Ответ 8
Иногда проблема возникает, если вы переместили свои классы, и это относится к старым классам, даже если они не существуют.
В этом случае просто сделайте это:
mvn eclipse:clean
mvn eclipse:eclipse
Это хорошо сработало для меня.