これが地図です
_@Autowired
private Map<String, ISendableConverter> converters;
_
およびISendableConverter
_public interface ISendableConverter {
ISendableMsg convert(BaseMessage baseMessage);
String getType();
}
_
ISendableConverter
を実装するクラスがいくつかあります
Spring _@Autowried
_アノテーションを使用して、変数converters
にそれらを注入したい。
値としてのクラスのインスタンス、およびキーとしてのメソッドgetType()
の結果。
このように
_@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";
}
}
_
これは可能ですか?そしてどうやって?
@ Resource のようなもので試してください-私はこのコードをテストしていません。
@Resource(name="converters")
private Map<String, ISendableConverter> converters;
または
@Value("#{converters}")
private Map<String, ISendableConverter> converters;
From Spring Docs
(..)それ自体がコレクションまたはマップタイプとして定義されているBeanは、タイプマッチングが適切に適用されないため、@ Autowiredを介して注入できません。このようなBeanには @ Resource を使用し、固有の名前で特定のコレクションまたはマップBeanを参照します。
これは、次のようにconverters
Beanを準備する場合にのみ機能します。
<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>
これも同様の質問です。
次のようなことができます:
@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);
});
}
Spring Java configuration:を使用して、選択したキーで自動的に初期化されたマップを作成できます。
@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;
}
このマップを挿入するより:
@Resource()
private Map<String, ISendableConverter> sendableConverters;
同じタイプのマップをさらに定義している場合、オプションでセレクタ文字列を@Resource
注釈に追加できます。
この方法で行う必要があるのは、Spring BeanによってISendableConverter
を実装することです。これは、上記で定義したMapに自動的に表示されます。実装ごとに手動でマップアイテムを作成する必要はありません。
このようなものを試してください、それは私のために働く
private Map<String, ISendableConverter> converters;
@Autowired
public void setUploadServices(Set<ISendableConverter> converters){
this.conveters = converters.stream()
.collect(Collectors.toMap(ISendableConverter::getType, Function.identity()));
}
コンストラクター注入を使用しても同じ結果が得られます。
private Map<String, ISendableConverter> converters;
@Autowired
public Foo(Set<ISendableConverter> converters) {
this.conveters = converters.stream()
.collect(Collectors.toMap(ISendableConverter::getType, Function.identity()));
}
マップと同じインターフェースのBeanを簡単に自動接続できます。キーはBean名です。そのため、コンポーネント自体に名前を付けた場合(つまり、静的な最終値を使用して、メソッドで使用することもできます)、これはすでにトリックを行う必要があります。
@Component("VOICE")
public class SendableVoiceMsgConverter implements ISendableConverter {
@Override
public ISendableMsg convert(BaseMessage baseMessage) {
// TODO Auto-generated method stub
return null;
}
}
コンポーネントの注釈に型名を直接追加するだけで、ジョブを実行できます。
これをより一般的にして、次のようなものを作成できます。
public interface BasicStrategy {
String getKey();
}
public final class StrategyMap<K extends BasicStrategy> extends HashMap<String, K> {
public StrategyMap(List<K> strategies) {
super(strategies.stream().collect(Collectors.toMap(K::getKey, Function.identity())));
}
@Override
public K get(Object key) {
BasicStrategy basicStrategy = super.get(key);
if (basicStrategy == null) {
throw new RuntimeException("No strategy found for key: '" + key + "'");
}
return (K) basicStrategy;
}
}
これで、このStrategyMap
を次のようにコードのあらゆる場所で使用できます。
private StrategyMap<ISendableConverter> converters;
@Autowired
public Foo(List<ISendableConverter> converters) {
this.conveters = new StrategyMap<>(converters);
}
このアプローチは、StrategyMap
の作成を一般化し、値が見つからない場合のロジックも集中化できます。
PS:もちろんISendableConverter
はBasicStrategy
インターフェイスを拡張する必要があります。