web-dev-qa-db-ja.com

Spring-注釈付きのMapでEnumキーを設定する方法

Enumクラスを持っています

public enum MyEnum{
    ABC;
}

私の「Mick」クラスにはこのプロパティがあります

private Map<MyEnum, OtherObj> myMap;

私はこの春のXML構成をしました。

<util:map id="myMap">
    <entry key="ABC" value-ref="myObj" />
</util:map>

<bean id="mick" class="com.x.Mick">
    <property name="myMap" ref="myMap" />
</bean>

これは結構です。
このxml設定をSpringアノテーションに置き換えたいです。
マップを自動配線する方法についてのアイデアはありますか?

ここでの問題は、xml configから@Autowiredアノテーション(MickクラスのmyMap属性上)に切り替えると、Springがこの例外をスローすることです。

nested exception is org.springframework.beans.FatalBeanException: Key type [class com.MyEnum] of map [Java.util.Map] must be assignable to [Java.lang.String]

Springは、文字列ABCをMyEnum.ABCオブジェクトとして認識できなくなりました。
何か案が?

ありがとう

39
mickthompson

これは私のために働いた...

私のSpringアプリケーションのコンテキスト:

<util:map id="myMap">
  <entry key="#{T(com.acme.MyEnum).ELEM1}" value="value1" />
  <entry key="#{T(com.acme.MyEnum).ELEM2}" value="value2" />
</util:map>

Mapが挿入される私のクラス:

public class MyClass {

    private @Resource Map<MyEnum, String> myMap;
}

注意すべき重要な点は、Springコンテキストでは、バージョン3.0以降でのみ使用可能なSpEL(Spring Expression Language)を使用したことです。そして、私のクラスでは@Resource、どちらも@Inject(私には役に立たなかった)または@Autowired(私はこれを試しませんでした)。私が知っている唯一の違いは@Resourceおよび@Autowiredは、前者がBean名で自動挿入し、後者がBeanタイプで自動挿入することです。

楽しい!

46
Cristian Ebbens

これは私にぴったりでしたが、Davidの答えと他のリンク(下記)を使ってつなぎ合わせることができました。

  • mapFactoryBean宣言のプロパティの名前を変更しないでください。
  • key-type属性が、マップでキーとして使用する列挙型を指していることを確認してください。

クラス

@Component
public class MyClass {

    private Map<MyEnum, ValueObjectInterface> valueMap;

    @Autowired
    public void setValueMap(final Map<MyEnum, ValueObjectInterface> valueMap) {
        this.valueMap= valueMap;
    }


}

Enum

    public enum MyEnum{
    FOO ("FOO"),
    BAR ("BAR"),
    BAZ ("BAZ");
}

XML構成ファイル:

<bean id="valueMap" class="org.springframework.beans.factory.config.MapFactoryBean">
    <property name="targetMapClass">
        <value>Java.util.HashMap</value>
    </property>
    <property name="sourceMap">
        <map key-type="com.company.packagepath.MyEnum">
          <entry key="FOO" value-ref="valueObject1" />
          <entry key="BAR" value-ref="valueObject2" />
          <entry key="BAZ" value-ref="valueObject3" />
        </map>
    </property>
</bean>

<bean id="valueObject1"  class="com.company.packagepath.ValueObject1" />
<bean id="valueObject2"  class="com.company.packagepath.ValueObject2" />
<bean id="valueObject3"  class="com.company.packagepath.ValueObject3" />

[〜#〜] links [〜#〜]

16
Tony R

アプリケーションコンテキスト

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd ">

<bean id="myProvider" class="com.project.MapProvider">
    <property name="myMap" ref="myMap"/>
</bean>

<util:map id="myMap" key-type="com.project.MyEnum" value-type="com.project.ValueObject">
    <entry>
        <key><value type="com.project.MyEnum">FOO</value></key>
        <ref bean="objectValue1"/>
    </entry>
</util:map>
</beans>

Javaクラス

package com.project;

public class MapProvider {

    private Map<MyEnum, ValueObject> myMap;

    public void setMyMap(Map<MyEnum, ValueObject> myMap) {
        this.myMap = myMap;
    }
}
5

する必要があります:

public class Mick {

  private Map<MyEnum, OtherObj> myMap;

  @Autowired
  public void setMyMap(Map<MyEnum, OtherObj> myMap) {
    this.myMap = myMap;
  }
}

http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-annotation-config をご覧ください

更新済み

問題は、utilスキーマに従って、キーまたは値のタイプを指定できないことです。ただし、独自のMapFactoryBeanを実装できます(org.springframework.beans.factory.config.MapFactoryBeanから継承するだけです)。 1つの注意点-ジェネリックな定義(実行時に消去されるとさえ考えられます)が邪魔にならないことに注意してください。

1

<util:map>要素にはキータイプがあります。キーのクラスを表す値型の属性。その価値。 key-type属性で列挙型の完全修飾クラスを指定すると、キーはマップの作成時にその列挙型に解析されます。

Springは、注入中に、マップのキーと値の型(マップを含むクラスで宣言されている)が、マップBeanのキーと値の型と割り当て互換であることを検証します。これが実際に例外を取得する場所です。

0
Gaetan

抽象またはインターフェイスではなく、Mapとして具体的なHashMapクラスを使用する必要があります。

public class Mick {

  private HashMap<MyEnum, OtherObj> myMap;

  @Autowired
  public void setMyMap(HashMap<MyEnum, OtherObj> myMap) {
    this.myMap = myMap;
  }
}


public class AppConfig
{
    @Bean
    public HashMap<MyEnum, OtherObj> myMap() { .. }
}
0