16

使用基于 Java 的配置,我正在尝试将映射枚举到 bean 引用的映射转换为纯 Java 配置(当前在 XML 和工作中),但似乎在文档中找不到任何内容;

目前,我的 XML 是这样的;

<util:map id="colourHanders" key-type="com.example.ColourEnum"
          value-type="com.example.ColourHandler">
    <entry key="white" value-ref="whiteColourHandler"/>
    <entry key="blue" value-ref="blueColourHandler"/>
    <entry key="red" value-ref="redColourHandler"/>
</util:map>

我确信这很容易,但同样,找不到关于如何在纯 Java 中表示它的任何内容(所以我没有任何 XML 配置文件)..

笔记; ColourHandlerbean 是使用 @Component 注释创建的,例如。

@Component
public class RedColourHandler implements ColourHander{
.....
}

并且 colourHandlers 的地图是这样引用的;

@Resource(name="colourHandlers")
    private Map<ColourHandlerEnum, ColourHandler> colourHandlers;

谢谢,

伊恩。

4

5 回答 5

15

你可能想要这样的东西:

@Configuration
public class MyConfiguration {
    @Bean public Map<ColourEnum, ColourHandler> colourHandlers() {
        Map<ColourEnum, ColourHandler> map = new EnumMap<>();
        map.put(WHITE, whiteHandler());
        // etc
        return map;
    }

    @Bean public ColourHandler whiteHandler() {
        return new WhiteHandler();
    }
}

如果您需要将处理程序保留为@Components,则可以将它们自动装配到配置类中:

@Configuration
public class MyConfiguration {
    @Autowired private WhiteColourHandler whiteColourHandler;

    @Bean public Map<ColourEnum, ColourHandler> colourHandlers() {
        Map<ColourEnum, ColourHandler> map = new EnumMap<>();
        map.put(WHITE, whiteColourHandler);
        return map;
    }
}
于 2012-11-08T16:42:48.070 回答
5

由于您已经为每个 ColorHandler 提供了一个唯一的类/@Component,我会让 Spring 弄清楚要使用什么(不需要 @Autowire 注入,也不需要任何其他创建方法):

@Configuration
public class MyConfiguration {
    @Bean public Map<ColourEnum, ColourHandler> colourHandlers(
            WhiteColourHandler whiteHandler, 
            BlueColourHandler blueHandler, 
            RedColourHandler redHandler) {
        Map<ColourEnum, ColourHandler> map = new EnumMap<>();
        map.put(WHITE, whiteHandler);
        map.put(BLUE, blueHandler);
        map.put(RED, redHandler);
        return map;
    }
}
于 2017-09-03T10:39:39.620 回答
2

这实际上非常简单,但您需要知道如何:

 @Autowired private ColourHandler whiteColourHandler;
 ...

 public Map<ColourEnum, ColourHandler> getColourHander() {
     Map<ColourEnum, ColourHandler> result = ...;
     map.put( ColourEnum.white, whiteColourHandler );
     ...
     return map;
 }

诀窍是您可以将 bean 注入到配置中。

于 2012-11-08T16:42:51.860 回答
2

类似于接受的答案,除了自动装配组件,您可以像往常一样在配置类中声明 bean 并将它们作为参数传递给 Map bean 方法:

@Configuration
public class MyConfiguration {
    @Bean public Map<ColourEnum, ColourHandler> colourHandlers(ColourHandler whiteHandler) {
        Map<ColourEnum, ColourHandler> map = new EnumMap<>();
        map.put(WHITE, whiteHandler);
        return map;
    }

    @Bean public ColourHandler whiteHandler() {
        return new WhiteHandler();
    }
}

另请注意,如果字段名称遵循与 bean 定义相同的命名约定,则将映射作为 @Resource 注入不需要注释的“名称”参数。

ie 这将在没有 name 参数的情况下工作:

@Resource
private Map<ColourHandlerEnum, ColourHandler> colourHandlers;

但这需要它:

@Resource(name="colourHandlers")
private Map<ColourHandlerEnum, ColourHandler> handlers;
于 2014-03-12T14:56:07.177 回答
0

您可以让ColourHandler类本身定义自己的类型,这样当您获得新类型时,您就不必不断更改配置类:

public interface ColourHander {
    ColourEnum getType();
}
@Component
public class RedColourHandler implements ColourHander{
    @Override
    public ColourEnum getType() {
        return ColourEnum.RED;
    }
}

在您的配置类中,您将获得所有ColourHandlers 并将它们映射到它们的类型。

@Configuration
public class MyConfiguration {
    @Bean 
    public Map<ColourEnum, ColourHandler> colourHandlers(List<ColourHandler> colourHandlers) {
        return colourHandlers.stream().collect(toMap(ColourHandler::getType, x -> x));
    }
}

请注意,如果IllegalStateException每种颜色有多个处理程序,您将得到一个,我猜这是预期的行为,您可以抓住它并抛出自己的。

于 2020-11-22T07:38:19.233 回答