嘗試在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();
}
PersonType.java
package com.jack.test;
public enum PersonType {
STUDENT, TEACHER;
}
Sex.java
package com.jack.test;
public enum Sex {
MALE, FEMALE;
}
Person.java
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;
}
}
App.java
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);
}
}
}
context.xml
<?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>