有没有办法在构建时通过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是"几乎免费",或者在印度,法拉利是"负担不起".在这两个国家,只有三辆汽车(确定性集),不多也不少,因此是枚举,但它们的"内在"值可能不同.因此,这是不可变的上下文初始化的情况.
你的意思是建立enum
自己?
我不认为这是可能的.您无法实例化枚举因为它们具有static
本质.所以我认为Spring IoC也无法创建 enums
.
另一方面,如果你需要设置初始化的东西,enum
请查看Spring IoC章节.(搜索枚举)有一个简单的例子,你可以使用.
我不认为可以从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)的名称重复为字符串.编辑:从好的方面来说,您可以将所有枚举的所有属性堆叠到每个语言/区域设置的一个属性文件中.
好吧,它非常繁琐,但它可以完成.
确实,Spring无法实例化枚举.但这不是问题 - Spring也可以使用工厂方法.
这是关键组成部分:
public class EnumAutowiringBeanFactoryPostProcessor implements BeanFactoryPostProcessor { private final List> enumClasses = new ArrayList<>(); public EnumAutowiringBeanFactoryPostProcessor(Class extends Enum>... enumClasses) { Collections.addAll(this.enumClasses, enumClasses); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { for (Class extends Enum> 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; } } }