Spring - 如何在带有注释的 Map 中设置 Enum 键

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1174308/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 03:54:33  来源:igfitidea点击:

Spring - How do you set Enum keys in a Map with annotations

springenumsannotations

提问by mickthompson

I've an Enum class

我有一个枚举类

public enum MyEnum{
    ABC;
}

than my 'Mick' class has this property

比我的“米克”班级有这个属性

private Map<MyEnum, OtherObj> myMap;

I've this spring xml configuration.

我有这个 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>

and this is fine.
I'd like to replace this xml configuration with Spring annotations.
Do you have any idea on how to autowire the map?

这很好。
我想用 Spring 注释替换这个 xml 配置。
您对如何自动装配地图有任何想法吗?

The problem here is that if I switch from xml config to the @Autowired annotation (on the myMap attribute of the Mick class) Spring is throwing this exception

这里的问题是,如果我从 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 is no more able to recognize the string ABC as a MyEnum.ABC object.
Any idea?

Spring 不再能够将字符串 ABC 识别为 MyEnum.ABC 对象。
任何的想法?

Thanks

谢谢

回答by Cristian Ebbens

This worked for me...

这对我有用...

My Spring application context:

我的 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>

My class where the Mapgets injected:

我的班级Map被注入:

public class MyClass {

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

The important things to note are that in the Spring context I used SpEL (Spring Expression Language) which is only available since version 3.0. And in my class I used @Resource, neither @Inject(it didn't work for me) nor @Autowired(I didn't try this). The only difference I'm aware of between @Resourceand @Autowired, is that the former auto-inject by bean name while the later does it by bean type.

需要注意的重要事项是在 Spring 上下文中我使用了 SpEL(Spring 表达式语言),它仅在 3.0 版之后可用。而在我的课堂我用@Resource,没有@Inject(它没有对我来说有效),也没有@Autowired(我没有尝试这个)。我所知道的唯一的区别@Resource@Autowired,是通过bean的名字,而后者由bean类型做它前自动注射。

Enjoy!

享受!

回答by Tony R

This one gave me fits but I was able to piece it together using David's answer and some other links (below).

这个给了我适合,但我能够使用大卫的答案和其他一些链接(如下)将它拼凑在一起。

  • do not change the names of the properties in the MapFactoryBean declaration.
  • ensure that key-type attribute points to the enum that you want to use as a key in the map.
  • 不要更改 MapFactoryBean 声明中的属性名称。
  • 确保 key-type 属性指向要用作映射中键的枚举。

Class

班级

@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 Config file:

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

链接

回答by Sergey Kravchenya

Application context

应用上下文

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

Java类

package com.project;

public class MapProvider {

    private Map<MyEnum, ValueObject> myMap;

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

回答by David Rabinowitz

Should be:

应该:

public class Mick {

  private Map<MyEnum, OtherObj> myMap;

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

Have a look at http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-annotation-config

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

Updated

更新

The problem is that according to the util schema, you cannot specify the key or value types. You can however to implement a MapFactoryBean of your own (just inherit from org.springframework.beans.factory.config.MapFactoryBean). One ceveat - notice that the generic definition (even thought erased in runtime) doesn't get in the way.

问题是,根据 util 架构,您不能指定键或值类型。但是,您可以实现自己的 MapFactoryBean(只需从 org.springframework.beans.factory.config.MapFactoryBean 继承)。一个 ceveat - 请注意通用定义(甚至认为在运行时已删除)并没有妨碍。

回答by Gaetan

The <util:map>element has key-type, resp. value-type attributes, that represents the class of the keys, resp. the values. If you specify the fully qualified class of your enum in the key-type attribute, the keys are then parsed into that enum when creating the map.

<util:map>元素具有键类型,分别为。值类型属性,表示键的类,resp。价值。如果在 key-type 属性中指定枚举的完全限定类,则在创建映射时将键解析为该枚举。

Spring verifies during injection that the map's key and value types -as declared in the class containing the map- are assignment-compatible with the key and value types of the map bean. This is actually where you get the exception from.

Spring 在注入过程中验证映射的键和值类型(在包含映射的类中声明)与映射 bean 的键和值类型的赋值兼容。这实际上是您从中获得异常的地方。

回答by Olga Pshenichnikova

You just need to use concrete Mapclass as HashMapand not abstract or interface:

您只需要使用具体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() { .. }
}

回答by Gerardo Roza

If you have a Mapwith an Enumvalues as keys, then consider using Java's EnumMapimplementation:

如果您有一个MapEnum值作为键,则考虑使用 Java 的EnumMap实现:

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

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

Here you also have a Baeldung post with some examples on how to use it:

在这里,您还有一个 Baeldung 帖子,其中包含一些有关如何使用它的示例:

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

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