Oli*_*ier 27 java enums spring
有没有办法在构建时通过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;
}
}
Run Code Online (Sandbox Code Playgroud)
假设应用程序必须部署在德国,Nanos是"几乎免费",或者在印度,法拉利是"负担不起".在这两个国家,只有三辆汽车(确定性集),不多也不少,因此是枚举,但它们的"内在"值可能不同.因此,这是不可变的上下文初始化的情况.
bru*_*nde 15
你的意思是建立enum自己?
我不认为这是可能的.您无法实例化枚举因为它们具有static本质.所以我认为Spring IoC也无法创建 enums.
另一方面,如果你需要设置初始化的东西,enum请查看Spring IoC章节.(搜索枚举)有一个简单的例子,你可以使用.
jav*_*ook 11
我不认为可以从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(...);
}
Run Code Online (Sandbox Code Playgroud)
在属性文件中,为每个特定区域设置一个,输入描述可能的内部枚举值的键:
Car.NANO.cost=Very cheap
Car.NANO.madeIn=India
Car.MERCEDES.cost=Expensive
...
Run Code Online (Sandbox Code Playgroud)
这种方法的唯一缺点是必须在Java代码中将枚举字段(cost,madeIn)的名称重复为字符串.编辑:从好的方面来说,您可以将所有枚举的所有属性堆叠到每个语言/区域设置的一个属性文件中.
好吧,它非常繁琐,但它可以完成.
确实,Spring无法实例化枚举.但这不是问题 - Spring也可以使用工厂方法.
这是关键组成部分:
public class EnumAutowiringBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
private final List<Class<? extends Enum>> 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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后以下测试类显示它的工作原理:
@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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
45610 次 |
| 最近记录: |