Spring - Как вы устанавливаете ключи Enum на карте с аннотациями
У меня класс Enum
public enum MyEnum{
ABC;
}
чем мой класс "Мик" имеет это свойство
private Map<MyEnum, OtherObj> myMap;
У меня есть эта конфигурация spring 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 аннотацию (в атрибуте 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.
Любая идея?
Спасибо
Ответы
Ответ 1
Это сработало для меня...
Мой контекст приложения 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 язык выражений), который доступен только с версии 3.0. И в моем классе я использовал @Resource
, ни @Inject
(это не сработало для меня), ни @Autowired
(я не пробовал это). Единственная разница, которую я знаю между @Resource
и @Autowired
, заключается в том, что прежняя автоинъекция с именем bean, а в дальнейшем - с типом bean.
Наслаждайтесь!
Ответ 2
Этот вопрос дал мне возможность, но я смог собрать его вместе, используя ответ Дэвида и некоторые другие ссылки (ниже).
- не изменяют имена свойств в объявлении 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" />
ССЫЛКА
Ответ 3
Контекст приложения
<?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;
}
}
Ответ 4
Должно быть:
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
Обновление
Проблема заключается в том, что согласно схеме использования вы не можете указывать типы ключей или значений. Однако вы можете реализовать собственный MapFactoryBean (просто наследуйте от org.springframework.beans.factory.config.MapFactoryBean). Один ceveat - обратите внимание, что общее определение (даже стираемое во время выполнения) не мешает.
Ответ 5
Элемент <util:map>
имеет тип ключа, соответственно. атрибуты value-type, которые представляют класс ключей, соответственно. ценности. Если вы укажете полностью квалифицированный класс вашего перечисления в атрибуте key-type, тогда ключи будут разбираться в этом перечислении при создании карты.
Spring проверяет во время инъекции, что ключ карты и типы значений, объявленные в классе, содержащем карту, являются совместимыми с назначением и ключевыми типами карты bean. На самом деле вы получаете исключение.
Ответ 6
Вам просто нужно использовать конкретный класс 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() { .. }
}
Ответ 7
Если у вас есть Map
со значениями Enum
в качестве ключей, рассмотрите возможность использования реализации Java EnumMap
:
https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/util/EnumMap.html
Здесь у вас также есть пост Baeldung с некоторыми примерами того, как его использовать:
https://www.baeldung.com/java-enum-map