尝试在spring的配置中的bean中注入Enum,debug跟踪了下spring-context 3.2.5.RELEASE的源码。
最终在类org.springframework.beans.TypeConverterDelegate中的attemptToConvertStringToEnum方法中进行了bean中Enum类型属性的转换。
private Object attemptToConvertStringToEnum(Class<?> requiredType, String trimmedValue, Object currentConvertedValue) { Object convertedValue = currentConvertedValue; if (Enum.class.equals(requiredType)) { // target type is declared as raw enum, treat the trimmed value as <enum.fqn>.FIELD_NAME int index = trimmedValue.lastIndexOf("."); if (index > - 1) { String enumType = trimmedValue.substring(0, index); String fieldName = trimmedValue.substring(index + 1); ClassLoader loader = this.targetObject.getClass().getClassLoader(); try { Class<?> enumValueType = loader.loadClass(enumType); Field enumField = enumValueType.getField(fieldName); convertedValue = enumField.get(null); } catch (ClassNotFoundException ex) { if(logger.isTraceEnabled()) { logger.trace("Enum class [" + enumType + "] cannot be loaded from [" + loader + "]", ex); } } catch (Throwable ex) { if(logger.isTraceEnabled()) { logger.trace("Field [" + fieldName + "] isn't an enum value for type [" + enumType + "]", ex); } } } } if (convertedValue == currentConvertedValue) { // Try field lookup as fallback: for JDK 1.5 enum or custom enum // with values defined as static fields. Resulting value still needs // to be checked, hence we don't return it right away. try { Field enumField = requiredType.getField(trimmedValue); convertedValue = enumField.get(null); } catch (Throwable ex) { if (logger.isTraceEnabled()) { logger.trace("Field [" + convertedValue + "] isn't an enum value", ex); } } } return convertedValue; }
在上面第一个if分支可以看出可在bean中注入Enum实例。在第二个if分支中可以看出能直接注入enum类型的属性。另外从这段代码的处理逻辑,可以看出不仅能注入enum实例,同时可以注入属性类型的静态属性。下面简单的写了个测试
Father.java
package com.jack.test; public class Father { public static final Father INSTANCE = new Father(); }
package com.jack.test; public enum PersonType { STUDENT, TEACHER; }
Sex.java
package com.jack.test; public enum Sex { MALE, FEMALE; }
package com.jack.test; public class Person { private Father father; private PersonType type; private Enum<Sex> sex; public Enum<Sex> getSex() { return sex; } public void setSex(Enum<Sex> sex) { this.sex = sex; } public Father getFather() { return father; } public void setFather(Father father) { this.father = father; } public PersonType getType() { return type; } public void setType(PersonType type) { this.type = type; } }
package com.jack.test; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.util.Assert; /** * @author jack.L */ public class App { public static void main(String[] args) { try (ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("context.xml")) { Person person = ctx.getBean(Person.class); Assert.isTrue(person.getFather() == Father.INSTANCE); Assert.isTrue(person.getType() == PersonType.STUDENT); Assert.isTrue(person.getSex() == Sex.MALE); } } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <bean id="person" class="com.jack.test.Person" p:father="INSTANCE" p:type="STUDENT" p:sex="com.jack.test.Sex.MALE" /> </beans>