java - component - ¿Puede Spring @Autowired Map?
spring autowired (4)
Aquí está el mapa
@Autowired
private Map<String, ISendableConverter> converters;
e ISendableConverter
public interface ISendableConverter {
ISendableMsg convert(BaseMessage baseMessage);
String getType();
}
Hay algunas clases que implementan ISendableConverter
Quiero inyectarlos en los converters
variables utilizando Spring Autowried.
la instancia de clase como valor y el resultado del método getType()
como clave.
como éste
@Component
public class SendableVoiceMsgConverter implements ISendableConverter {
@Override
public ISendableMsg convert(BaseMessage baseMessage) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getType() {
return "VOICE";
}
}
¿es posible? ¿y cómo?
Intenta algo como esto, me funciona
private Map<String, ISendableConverter> converters;
@Autowired
public void setUploadServices(Set<ISendableConverter> converters){
this.conveters = converters.stream()
.collect(Collectors.toMap(ISendableConverter::getType, Function.identity()));
}
El mismo resultado se puede lograr usando la inyección de constructor:
private Map<String, ISendableConverter> converters;
@Autowired
public Foo(Set<ISendableConverter> converters) {
this.conveters = converters.stream()
.collect(Collectors.toMap(ISendableConverter::getType, Function.identity()));
}
Pruebe con algo como @Resource - No he probado este código.
@Resource(name="converters")
private Map<String, ISendableConverter> converters;
o
@Value("#{converters}")
private Map<String, ISendableConverter> converters;
Desde Spring Docs
(..) los beans que están definidos como una colección o tipo de mapa no se pueden inyectar a través de @Autowired, porque la coincidencia de tipos no se aplica adecuadamente a ellos. Utilice @Resource para dichos beans, refiriéndose a la colección específica o al bean de mapa por nombre único.
Esto debería funcionar, solo si usted prepara converters
como este:
<util:map id="converters" scope="prototype" map-class="java.util.HashMap"
key-type="java.lang.String" value-type="...ISendableConverter">
<entry key="VOICE" value="sendableVoiceMsgConverter" />
</util:map>
Esta es también una pregunta similar:
Puede crear un mapa inicializado automáticamente con las claves de su elección utilizando la configuración de Spring Java:
En la clase anotada con la anotación @Configuration
:
@Autowired
private List<ISendableConverter> sendableConverters;
@Bean
public Map<String, ISendableConverter> sendableConvertersMap() {
Map<String, ISendableConverter> sendableConvertersMap = new HashMap<>();
for (ISendableConverter converter : sendableConverters) {
sendableConvertersMap.put(converter.getType(), converter);
}
return sendableConvertersMap;
}
Que inyectas este mapa con:
@Resource()
private Map<String, ISendableConverter> sendableConverters;
Opcionalmente, puede agregar alguna cadena de selección a su anotación @Resource
si ha definido más mapas del mismo tipo.
De esta manera, todo lo que tiene que hacer es implementar ISendableConverter
por su Spring Bean y aparecerá automáticamente en el mapa definido anteriormente. No es necesario crear elementos de mapa a mano para cada implementación.
Puedes hacer algo como esto:
@SuppressWarnings("unused")
private List<OneTypeImageLoader> imageLoaders;
private Map<String, OneTypeImageLoader> imageLoaderMap=new HashMap<>();
@Autowired
public void setImageLoaders(List<OneTypeImageLoader> imageLoaders) {
this.imageLoaders = imageLoaders;
imageLoaders.forEach(l-> {
imageLoaderMap.put(l.getType(), l);
});
}