web-dev-qa-db-ja.com

@Autowired Mapをスプリングできますか?

これが地図です

_@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";
    }
}
_

これは可能ですか?そしてどうやって?

27
Joe

@ 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>

これも同様の質問です。

15
MariuszS

次のようなことができます:

@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);
    });
}
10
TimYi

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に自動的に表示されます。実装ごとに手動でマップアイテムを作成する必要はありません。

9
Ondrej Bozek

このようなものを試してください、それは私のために働く

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()));
}
8
Sergii Bishyr

マップと同じインターフェースのBeanを簡単に自動接続できます。キーはBean名です。そのため、コンポーネント自体に名前を付けた場合(つまり、静的な最終値を使用して、メソッドで使用することもできます)、これはすでにトリックを行う必要があります。

0
Manuel Polacek
@Component("VOICE")
public class SendableVoiceMsgConverter implements ISendableConverter {

    @Override
    public ISendableMsg convert(BaseMessage baseMessage) {
        // TODO Auto-generated method stub
        return null;
    }
}

コンポーネントの注釈に型名を直接追加するだけで、ジョブを実行できます。

0
Rigeborod

これをより一般的にして、次のようなものを作成できます。

    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:もちろんISendableConverterBasicStrategyインターフェイスを拡張する必要があります。

0
Borys Rudenko