Annotation-le nom de bean spécifié entre en conflit avec le bean Def existant et non compatible

J'ai un problème avec certaines définitions de Spring bean. J'ai quelques fichiers XML de contexte qui sont chargés par ma méthode main (), et les deux contiennent presque exclusivement une balise. Lorsque ma méthode principale démarre, j'obtiens cette erreur de 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]

Les deux classes DAO sont annotées de cette façon:

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

Le dao en mémoire a également l'annotation @Repository("converterDAO"). Le dao est référencé dans d'autres classes comme ceci:

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

Je veux un DAO pour remplacer la définition de l'autre, qui, comme je l'ai toujours compris, était l'une des principales raisons d'utiliser un cadre DI en premier lieu. Je le fais avec des définitions xml depuis des années et je n'ai jamais eu de problèmes. Mais pas avec les analyses de composants et les définitions de bean annotées? Et que signifie Le printemps quand il dit qu'ils ne sont pas"compatibles"? Ils implémentent la même interface, et ils sont automatiquement câblés dans des champs de ce type d'interface. Pourquoi diable ne le sont ils pas sont-ils compatibles?

Quelqu'un peut-il me fournir un moyen pour un bean annoté et numérisé par composant de remplacer un autre?

-Mike

37
demandé sur user1283068 2012-12-10 16:52:17

7 réponses

Dans un fichier XML, il y a une séquence de déclarations, et vous pouvez remplacer une définition précédente par une définition plus récente. Lorsque vous utilisez des annotations, il n'y a pas de notion de avant ou après. Tous les haricots sont au même niveau. Vous avez défini deux haricots avec le même nom, et Spring ne sait pas lequel il devrait choisir.

Donnez-leur un nom différent ( staticConverterDAO, inMemoryConverterDAO par exemple), créez un alias dans le fichier XML Spring ( theConverterDAO par exemple), et utilisez cet alias lors de l'injection du convertisseur:

@Autowired @Qualifier("theConverterDAO")
27
répondu JB Nizet 2012-12-10 21:49:03

J'ai eu un problème similaire, avec deux bibliothèques jar (app1 et app2) dans un projet. Le bean "BeanName" est défini dans app1 et est étendu dans app2 et le bean redéfini avec le même nom.

Dans app1:

package com.foo.app1.pkg1;

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

Dans app2:

package com.foo.app2.pkg2;

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

Cela provoque l'exception ConflictingBeanDefinitionException dans le chargement de applicationContext en raison du même nom de bean de Composant.

Pour résoudre ce problème, dans le fichier de configuration 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>

Donc la Class1 est exclu pour être automatiquement scanné par un composant et affecté à un bean, évitant ainsi le conflit de nom.

25
répondu user1897261 2014-01-30 21:15:29

J'ai eu un problème similaire avec Ressort 4.x en utilisant @ RestController. Deux paquets différents avaient une classe avec le même nom...

package com.x.catalog

@RestController
public class TextureController {
...

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

Le correctif était facile...

package com.x.catalog

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

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

Le problème semble être que l'annotation est autowired et prend le nom de classe par défaut. Lui donner un nom explicite dans l'annotation @ RestController vous permet de conserver les noms de classe.

17
répondu Ian Newland 2016-04-24 03:11:12

J'ai eu un problème similaire, et c'était parce qu'un de mes haricots avait été déplacé dans un autre répertoire récemment. J'avais besoin de faire un "build clean" en supprimant le répertoire build/classes/java et le problème a disparu. (Le message d'erreur avait les deux chemins de fichiers différents en conflit les uns avec les autres, bien que je savais que l'on ne devrait plus exister.)

2
répondu Rock Lee 2018-06-12 19:32:00

Scénario:

Je travaille sur un projet Gradle multi-modules.

Les Modules sont:

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

Donc, nous avons principalement préparé un composant [locationRecommendHttpClientBuilder ] dans le module geo.

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

Application-contexte.xml

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

Ensuite, il est décidé d'ajouter ce composant dans le modulecore .

Un ingénieur a le code précédent pour le module geo , puis il a pris le dernier module de base, mais il a oublié de prendre la dernière geo module.

Donc, le composant [locationRecommendHttpClientBuilder ] est double fois dans son projet et il obtenait l'erreur suivante.

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]

Procédure De Solution:

Après le retrait de la composante de geo module, composant[locationRecommendHttpClientBuilder] n'est disponible que dans base module. Donc, il n'y a pas de situation de conflit. Problème est résolu de cette manière.

0
répondu SkyWalker 2018-05-18 12:31:47

J'ai aussi eu un problème similaire. J'ai construit le projet à nouveau et le problème a été résolu.

La raison en est qu'il existe déjà des séquences définies pour les noms de bean spécifiés par Annotation, dans un fichier. Lorsque nous faisons un changement sur ce nom de bean et essayons d'exécuter L'application Spring ne peut pas identifier lequel choisir. C'est pourquoi, il affiche cette erreur.

Dans mon cas, j'ai supprimé la classe bean précédente du projet et ajouté le même nom de bean à une nouvelle classe bean. Donc le printemps a le définition précédente pour la classe Bean supprimée dans un fichier et qui entre en conflit avec la classe nouvellement ajoutée lors de la compilation. Donc, si vous faites un 'build clean', les définitions précédentes pour les classes bean seront supprimées et la compilation réussira.

0
répondu Pathirennehelage Nadeeshani 2018-07-12 06:08:35

J'ai rencontré ce problème lorsque j'ai importé un projet two dans l'espace de travail. Il a créé un pot différent en quelque sorte afin que nous puissions supprimer les pots et les fichiers de classe et construire à nouveau le projet pour obtenir les dépendances.

0
répondu Roopal 2018-08-31 20:16:41