Spring - Как установить ключи Enum на карте с аннотациями

У меня есть класс Enum

public enum MyEnum{
    ABC;
}

чем у моего класса "Мик" есть это свойство

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-конфигурации на аннотацию @Autowired (в атрибуте myMap класса Mick), 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.
Есть идеи?

Спасибо


person mickthompson    schedule 23.07.2009    source источник
comment
Непонятно, что вы пытаетесь сделать. Какие аннотации вы думаете?   -  person skaffman    schedule 24.07.2009
comment
Я хотел бы использовать аннотацию @Autowired, но она не работает. Должен ли я указать что-то еще, чтобы Spring обрабатывал это значение Key как Enum вместо String?   -  person mickthompson    schedule 26.07.2009


Ответы (7)


Это сработало для меня ...

Мой контекст приложения 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 я использовал SpEL (Spring Expression Language), который доступен только с версии 3.0. И в своем классе я использовал @Resource, ни @Inject (у меня не сработало), ни @Autowired (я не пробовал). Единственное различие между @Resource и @Autowired, о котором я знаю, заключается в том, что в первом случае вводится автоматически по имени компонента, а во втором - по типу компонента.

Наслаждаться!

person Cristian Ebbens    schedule 22.10.2010
comment
Не забудьте использовать "$" вместо "." для отделения внутреннего перечисления от внешнего класса в Spring EL. - person Amir Moghimi; 08.02.2011
comment
Просто продолжение, которое @Autowired также даст Key type [class com.foo.Bar$BAZ] of map [java.util.Map] must be assignable to [java.lang.String], @Resource - победитель. +1 @ Амир, $ - ошибка. - person markdsievers; 28.08.2011
comment
Вопрос сказал, что я хотел бы заменить эту xml-конфигурацию аннотациями Spring. но здесь все еще есть конфигурационный XML. Означает ли это, что вы не можете сделать это в Spring исключительно с помощью аннотаций? - person Jonik; 15.11.2011
comment
@Jonik Я думаю, что предполагаемая замена была частью bean-компонента и инъекции ресурсов, а не частью карты. В противном случае я не уверен, почему был выбран этот ответ. - person Patrick; 12.12.2012
comment
Большое вам спасибо за это. Работает только @ Resource. Я попробовал @ Autowired, но ничего не вышло. Странно, но я просто выберу @ Resource - person Sanjiv Jivan; 04.03.2014

Это меня устроило, но я смог собрать его воедино, используя ответ Дэвида и некоторые другие ссылки (ниже).

  • не изменяйте имена свойств в объявлении MapFactoryBean.
  • убедитесь, что атрибут типа ключа указывает на перечисление, которое вы хотите использовать в качестве ключа на карте.

Класс

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

ССЫЛКИ

person Tony R    schedule 22.03.2011

Контекст приложения

<?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;
    }
}
person Sergey Kravchenya    schedule 10.09.2012
comment
Ответ требует немного большего объяснения того, что вы здесь перечислили. - person Markus; 06.10.2012
comment
Я создал карту с перечислением в качестве ключа и использовал ее в качестве аргумента установки. Думал это очевидно :) - person Sergey Kravchenya; 09.10.2012

Должно быть:

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). Одно предположение - обратите внимание, что общее определение (даже мысль, стертая во время выполнения) не мешает.

person David Rabinowitz    schedule 26.07.2009
comment
Привет, Дэвид, я знаю об аннотации @Autowired. Проблема здесь в том, что если я автоматически подключу карту, Spring больше не сможет распознать строку ABC как объект MyEnum.ABC. С конфигурацией XML он работает нормально, с конфигурацией аннотаций это исключение выбрасывает вложенное исключение org.springframework.beans.FatalBeanException: тип ключа [класс com.MyEnum] карты [java.util.Map] должен быть назначен [java.lang] .Нить] - person mickthompson; 26.07.2009

Элемент <util:map> имеет тип ключа, соответственно. атрибуты типа значения, представляющие класс ключей, соотв. ценности. Если вы укажете полностью определенный класс своего перечисления в атрибуте key-type, ключи затем будут преобразованы в это перечисление при создании карты.

Spring проверяет во время внедрения, что типы ключей и значений карты, объявленные в классе, содержащем карту, совместимы по назначению с типами ключей и значений компонента карты. На самом деле это то место, откуда вы получаете исключение.

person Gaetan    schedule 20.10.2009

Вам просто нужно использовать конкретный 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() { .. }
}
person Olga Pshenichnikova    schedule 15.08.2018

Если у вас есть Map со значениями Enum в качестве ключей, рассмотрите возможность использования EnumMap реализации Java:

https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/util/EnumMap.html

Здесь у вас также есть сообщение Baeldung с некоторыми примерами его использования:

https://www.baeldung.com/java-enum-map

person Gerardo Roza    schedule 22.09.2019