true resource ejemplo spring spring-mvc dependency-injection annotations autowired

resource - spring autowiring with unique beans: Spring esperaba una sola haba pero encontrĂ³ 2



@resource spring (4)

Estoy intentando conectar automáticamente algunos beans (para inyección de dependencia) usando Spring para una aplicación web. Un control bean contiene otro bean que a su vez contiene un hashmap de otro conjunto de beans. Por ahora, el mapa solo tiene una entrada. Cuando corro en tomcat y llamo al servicio recibo un error que dice que el segundo bean (contenido en el controlador) no es único

No unique bean of type [com.hp.it.km.search.web.suggestion.SuggestionService] is defined: expected single matching bean but found 2: [suggestionService, SuggestionService]

No puedo ver dónde estoy definiendo el frijol dos veces, sin embargo, soy nuevo en Spring y autoelaborador, por lo que me podría estar perdiendo algo fundamental. Código fuente para xml y 2 clase enumerados a continuación ...

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <context:component-scan base-package="com.hp.it.km.search.web.suggestion" /> <mvc:annotation-driven /> <context:annotation-config /> <bean id="SuggestionController" class="com.hp.it.km.search.web.suggestion.SuggestionController"> <property name="service"> <ref bean="SuggestionService" /> </property> </bean> <bean id="SuggestionService" class="com.hp.it.km.search.web.suggestion.SuggestionService"> <property name="indexSearchers"> <map> <entry key="KMSearcher"> <ref bean="KMSearcherBean"></ref></entry> </map> </property> </bean> <bean id="KMSearcherBean" class="com.hp.it.km.search.web.suggestion.SuggestionIndexSearcher"> <constructor-arg index="0" value="KMSearcher" /> <constructor-arg index="1" value="C://dev//workspace//search-restful-webapp//src//main//resources//indexes//keyword" /> </bean>

Los asscoaites de clase con el controlador de autowired y el bean de servicio están aquí ...

@Controller public class SuggestionController { private SuggestionService service; @Autowired public void setService(SuggestionService service) { this.service = service; } public SuggestionService getService() { return service; }

y...

@Component public class SuggestionService { private Map<String, IndexSearcher> indexSearchers = new HashMap<String, IndexSearcher>(); @Autowired public void setIndexSearchers(Map<String, IndexSearcher> indexSearchers) { this.indexSearchers = indexSearchers; } public SuggestionService() { super(); }

¡Por favor ayuda!


El problema se debe a que tiene un bean de tipo SuggestionService creado a través de la anotación @Component y también a través de la configuración XML. Como explicó JB Nizet, esto conducirá a la creación de un bean con el nombre ''suggestionService'' creado a través de @Component y otro con el nombre ''SuggestionService'' creado a través de XML.

Cuando refiera SuggestionService por @Autowired, en su controlador, Spring se autoelerece "por tipo" de manera predeterminada y encontrará dos beans de tipo ''SuggestionService''

Podrías hacer lo siguiente

  1. Elimine @Component de su Servicio y dependa del mapeo a través de XML - Más fácil
  2. Elimine SuggestionService de XML y autoelene las dependencias - use util: map para inyectar el mapa de indexSearch.
  3. Use @Resource en lugar de @Autowired para elegir el bean por su nombre.

    @Resource("suggestionService") private SuggestionService service;

o

@Resource("SuggestionService") private SuggestionService service;

ambos deberían funcionar. El tercero es una solución sucia y es mejor resolver el conflicto de frijol a través de otros medios.


Para mí fue el caso de tener dos beans implementando la misma interfaz. Una era una prohibición falsa por el bien de la prueba unitaria que estaba en conflicto con el frijol original. Si usamos

@component ("suggestionServicefake")

, sigue haciendo referencia a suggestionService. Así que eliminé @component y solo usé

@Qualifier ("suggestionServicefake")

que resolvió el problema


Si no me equivoco, el nombre del bean predeterminado de un bean declarado con @Component es el nombre de su clase, su primera letra en minúsculas. Esto significa que

@Component public class SuggestionService {

declara un bean de tipo SuggestionService , y de nombre suggestionService . Es equivalente a

@Component("suggestionService") public class SuggestionService {

o para

<bean id="suggestionService" .../>

Está redefiniendo otro bean del mismo tipo, pero con un nombre diferente, en el XML:

<bean id="SuggestionService" class="com.hp.it.km.search.web.suggestion.SuggestionService"> ... </bean>

Por lo tanto, especifique el nombre del bean en la anotación para que sea SuggestionService , o use el ID suggestionService en el XML (no olvide modificar también el elemento <ref> o eliminarlo, ya que no es necesario) . En este caso, la definición XML anulará la definición de la anotación.


Si tiene 2 beans de la misma clase autoconectados a una clase, debe usar @Qualifier ( Spring Autowiring @Qualifier example ).

Pero parece que su problema proviene de una sintaxis Java incorrecta.

Su objeto debe comenzar con letra minúscula

SuggestionService suggestion;

Su setter también debe comenzar con minúsculas y el nombre del objeto debe estar con mayúsculas.

public void setSuggestion(final Suggestion suggestion) { this.suggestion = suggestion; }