当前位置:  开发笔记 > 编程语言 > 正文

使用Spring IoC设置枚举值

如何解决《使用SpringIoC设置枚举值》经验,为你挑选了3个好方法。

有没有办法在构建时通过Spring IoC设置这样的枚举值?

我想要做的是在类加载时注入下面的代码片段中硬编码的值:

public enum Car
{
        NANO ("Very Cheap", "India"),
        MERCEDES ("Expensive", "Germany"),
        FERRARI ("Very Expensive", "Italy");

        public final String cost;
        public final String madeIn;

        Car(String cost, String madeIn)
        {
                this.cost= cost;
                this.madeIn= madeIn;
        }

}

假设应用程序必须部署在德国,Nanos是"几乎免费",或者在印度,法拉利是"负担不起".在这两个国家,只有三辆汽车(确定性集),不多也不少,因此是枚举,但它们的"内在"值可能不同.因此,这是不可变的上下文初始化的情况.



1> bruno conde..:

你的意思是建立enum自己?

我不认为这是可能的.您无法实例化枚举因为它们具有static本质.所以我认为Spring IoC也无法创建 enums.

另一方面,如果你需要设置初始化的东西,enum请查看Spring IoC章节.(搜索枚举)有一个简单的例子,你可以使用.



2> javashlook..:

我不认为可以从Spring的ApplicationContext配置中完成.但是,你真的需要Spring完成它,或者你能否使用ResourceBundle解决简单的外部化问题; 像这样:

public enum Car
{
    NANO,
    MERCEDES,
    FERRARI;

    public final String cost;
    public final String madeIn;

    Car()
    {
            this.cost = BUNDLE.getString("Car." + name() + ".cost");
            this.madeIn = BUNDLE.getString("Car." + name() + ".madeIn");
    }

    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle(...);

}

在属性文件中,为每个特定区域设置一个,输入描述可能的内部枚举值的键:

Car.NANO.cost=Very cheap
Car.NANO.madeIn=India
Car.MERCEDES.cost=Expensive
...

这种方法的唯一缺点是必须在Java代码中将枚举字段(cost,madeIn)的名称重复为字符串.编辑:从好的方面来说,您可以将所有枚举的所有属性堆叠到每个语言/区域设置的一个属性文件中.



3> Tom McIntyre..:

好吧,它非常繁琐,但它可以完成.

确实,Spring无法实例化枚举.但这不是问题 - Spring也可以使用工厂方法.

这是关键组成部分:

public class EnumAutowiringBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    private final List> enumClasses = new ArrayList<>();

    public EnumAutowiringBeanFactoryPostProcessor(Class... enumClasses) {
        Collections.addAll(this.enumClasses, enumClasses);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        for (Class enumClass : enumClasses) {
            for (Enum enumVal : enumClass.getEnumConstants()) {
                BeanDefinition def = new AnnotatedGenericBeanDefinition(enumClass);
                def.setBeanClassName(enumClass.getName());
                def.setFactoryMethodName("valueOf");
                def.getConstructorArgumentValues().addGenericArgumentValue(enumVal.name());
                ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition(enumClass.getName() + "." + enumVal.name(), def);
            }
        }
    }
}

然后以下测试类显示它的工作原理:

@Test
public class AutowiringEnumTest {

    public void shouldAutowireEnum() {
        new AnnotationConfigApplicationContext(MyConig.class);

        assertEquals(AutowiredEnum.ONE.myClass.field, "fooBar");
        assertEquals(AutowiredEnum.TWO.myClass.field, "fooBar");
        assertEquals(AutowiredEnum.THREE.myClass.field, "fooBar");
    }

    @Configuration
    public static class MyConig {

        @Bean
        public MyClass myObject() {
            return new MyClass("fooBar");
        }

        @Bean
        public BeanFactoryPostProcessor postProcessor() {
            return new EnumAutowiringBeanFactoryPostProcessor(AutowiredEnum.class);
        }
    }

    public enum AutowiredEnum {
        ONE,
        TWO,
        THREE;

        @Resource
        private MyClass myClass;

    }

    public static class MyClass {

        private final String field;

        public MyClass(String field) {
            this.field = field;
        }
   }

}

推荐阅读
linjiabin43
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有