2011-02-09 47 views
8

Estoy usando Spring 3.0.4. Tengo algunos frijoles que usan la anotación @Autowired en Maps. Estos mapas se definen dentro de un archivo application-context.xml (ya que estos mapas se construyen utilizando varios métodos de fábrica).Autowiring Map no funciona como se esperaba

Cuando uso mi depurador, puedo ver que el mapa se construye utilizando la id del bean correctamente (esperado). Sin embargo, una vez que se inicia el proceso de autoenvío, afirma que no puede encontrar un bean con el ID que acaba de crearse.

pieza de código:

@Autowired 
@Qualifier("dienstverbandMap") 
private Map<String, String> dienstverbandMap; 

Pedazo de contexto xml:

<bean class="java.util.HashMap" id="dienstverbandMap" factory-bean="someFactoryMethod" factory-method="getMappedMap"/> 

Detalle importante, cuando cambio el tipo de java.lang.Object tanto en mi clase y el contexto XML se recibe cableado De hecho, puedo convertirlo a HashMap en mi código y hacer que todo funcione. Pero eso no es lo que quiero obviamente.

¿Alguien tiene una explicación de lo que estoy haciendo mal?

Respuesta

4

Creo que esto tiene algo que ver con los parámetros de tipo para dienstverbandMap. La inyección solo se puede realizar de forma segura si Spring puede darse cuenta de que la instancia de bean (un HashMap) se instancia realmente como HashMap<String, String>. Spring podría estar perdiendo los parámetros de tipo debido a que el tipo declarado del bean es un tipo sin procesar.

Otra posibilidad es que la firma del resultado del método de fábrica sea incorrecta; p.ej. Mapa en lugar de HashMap, o un HashMap en bruto en lugar de HashMap<String, String>.

(Algunas de estas teorías ha podido ser desvirtuado si nos mostró la declaración del método de fábrica.)


Por cierto, de acuerdo con los comentarios en la primavera en grano 2.0 DTD y 3.0 XSD, el atributo class no se usa si proporciona un atributo factory-bean. ¿Has intentado dejarlo por completo?

+1

Tienes razón. La firma de mi método de fábrica devuelve Map <>, cuando cambié eso a HashMap, todo comenzó a funcionar. ¡¡Gracias!! :) –

+0

Me imaginé, la fábrica implementó una interfaz que forzó el tipo de retorno a ser un mapa (o más específico). Sin embargo, incluso entonces no funcionó. Tuve que cambiar la interfaz para que esto funcione. Yuk :) –

0

Estoy bastante seguro de que su método de fábrica vuelve java.util.Map, no java.util.HashMap, así que supongo que probablemente podría hacer esto:

<bean class="java.util.Map" id="dienstverbandMap" 
     factory-bean="someFactoryMethod" factory-method="getMappedMap"/> 

de responsabilidad: No estoy seguro de si la primavera le permitirá hacer eso como Map es una interfaz, pero vale la pena intentarlo.

+0

He intentado establecer el tipo de bean en java.util.Map. Pero fue en vano. Aunque gracias por tu sugerencia. –

5

3.11.3. Fine-tuning annotation-based autowiring with qualifiers:

Cita: Si tiene la intención de expresar la inyección de anotación impulsada por su nombre, no utilizan principalmente @Autowired - incluso si es técnicamente capaz de referirse a un nombre de frijol a través @Qualifier valores. En su lugar, prefiera la anotación JSR-250 @Resource que se define semánticamente para identificar un componente objetivo específico por su nombre único, con el tipo declarado como irrelevante para el proceso de coincidencia.

Como consecuencia específica de esta diferencia semántica, los beans que a su vez se definen como una colección o tipo de mapa no se pueden inyectar a través de @Autowired ya que la coincidencia de tipos no se aplica correctamente a ellos. Use @Resource para dichos beans, haciendo referencia al bean de colección/mapa específico por nombre único.

+0

¿Hay más documentación que recomiendas con respecto a la anotación @Resource? –

+1

Solo una nota, cuando probé la anotación de Recursos, funcionó bien en Tomcat, pero no funcionó en JBoss. Parece que el controlador de anotaciones @Resource depende de la plataforma. – BillMan

0

La definición de bean para el mapa no contiene los parámetros de tipo, por lo que el cableado automático no puede confirmar que sea del tipo correcto.

Si usa <util:map> puede especificar los parámetros de tipo, pero obviamente no puede usar su propio método de fábrica. Las únicas otras soluciones son hacer que su bean requiera un Map crudo (malo) o cablee explícitamente los mapas en la definición del bean (mejor).

Cuestiones relacionadas