web-dev-qa-db-fra.com

Spring - Comment définir les clés Enum dans une carte avec des annotations

J'ai un cours d'énum

public enum MyEnum{
    ABC;
}

que ma classe 'Mick' a cette propriété

private Map<MyEnum, OtherObj> myMap;

J'ai cette configuration de printemps 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>

et c'est bien.
J'aimerais remplacer cette configuration XML par des annotations Spring.
Avez-vous une idée sur la façon de virer automatiquement la carte?

Le problème ici est que si je passe de la configuration xml à l'annotation @Autowired (sur l'attribut myMap de la classe Mick), Spring lève cette exception.

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 n'est plus en mesure de reconnaître la chaîne ABC en tant qu'objet MyEnum.ABC. 
Une idée?

Merci 

39
mickthompson

Cela a fonctionné pour moi ...

Mon contexte d'application 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>

Ma classe où la Map est injectée:

public class MyClass {

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

Les points importants à noter sont que, dans le contexte Spring, j’utilisais SpEL (Spring Expression Language), qui n’est disponible que depuis la version 3.0. Et dans ma classe, j'ai utilisé @Resource, ni @Inject (cela n'a pas fonctionné pour moi) ni @Autowired (je n'ai pas essayé cela). La seule différence que je connaisse entre @Resource et @Autowired est que l'ancien auto-injecte par nom de bean alors que le dernier le fait par type.

Prendre plaisir!

46
Cristian Ebbens

Celui-ci m'a donné des crises, mais j'ai pu le reconstituer en utilisant la réponse de David et quelques autres liens (ci-dessous).

  • ne changez pas les noms des propriétés dans la déclaration MapFactoryBean.
  • assurez-vous que l'attribut de type de clé pointe vers l'énum que vous voulez utiliser comme clé dans la carte.

Classe

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

Fichier de configuration 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" />

LIENS

16
Tony R

Contexte d'application

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

classe Java

package com.project;

public class MapProvider {

    private Map<MyEnum, ValueObject> myMap;

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

Devrait être:

public class Mick {

  private Map<MyEnum, OtherObj> myMap;

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

Regardez http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-annotation-config

Mis à jour

Le problème est que, selon le schéma util, vous ne pouvez pas spécifier les types de clé ou de valeur. Vous pouvez cependant implémenter votre propre MapFactoryBean (héritez simplement de org.springframework.beans.factory.config.MapFactoryBean). One ceveat - remarquez que la définition générique (même les pensées effacées au moment de l'exécution) n'interfère pas.

1
David Rabinowitz

L'élément <util:map> a le type de clé, resp. attributs de type valeur, qui représente la classe des clés, resp. les valeurs. Si vous spécifiez la classe pleinement qualifiée de votre enum dans l'attribut key-type, les clés sont ensuite analysées dans cette enum lors de la création de la carte.

Spring vérifie lors de l'injection que les types de clé et de valeur de la carte - tels que déclarés dans la classe contenant la carte - sont compatibles avec les types de clé et de valeur du bean map. C'est en fait là que vous obtenez l'exception.

0
Gaetan

Vous avez juste besoin d'utiliser la classe Map comme HashMap et non d'abstraction ou d'interface

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
Olga Pshenichnikova