一省核、簡介
??MetaClass
通過對 Reflector
和 PropertyTokenizer
組合使用易迹,實(shí)現(xiàn)了對復(fù)雜的屬性表達(dá)式的解析砌们,并實(shí)現(xiàn)了獲取指定屬性描述信息的功能。
二旷赖、成員屬性
private ReflectorFactory reflectorFactory;
private Reflector reflector;
-
reflectorFactory
:負(fù)責(zé)創(chuàng)建和緩存 Reflector 對象的工廠類。 -
reflector
:傳入的 Class 對象對應(yīng)的 Reflector 對象探膊,該對象保存了該類相關(guān)的元信息杠愧。
三、構(gòu)造方法
// 構(gòu)造方法逞壁,被靜態(tài)方法#forClass內(nèi)部調(diào)用
private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
this.reflectorFactory = reflectorFactory;
this.reflector = reflectorFactory.findForClass(type);
}
??這是一個(gè)私有構(gòu)造方法流济,構(gòu)造函數(shù)會(huì)被靜態(tài)內(nèi)部類 #forClass()
調(diào)用。
四腌闯、方法功能
1绳瘟、MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory)
【功能】創(chuàng)建指定類的 MetaClass 對象(創(chuàng)建 Reflector 對象的工廠對象可以用戶指定)。
【源碼與注解】
// 根據(jù)傳入的Class對象和反射工廠對象創(chuàng)建對應(yīng)的MetaClass對象
public static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) {
return new MetaClass(type, reflectorFactory);
}
2姿骏、MetaClass metaClassForProperty(String name)
【功能】根據(jù)指定的類屬性名創(chuàng)建類屬性類型對應(yīng)的MataClass對象糖声。
【源碼與注解】
// 根據(jù)類屬性名創(chuàng)建類屬性類型對應(yīng)的MataClass對象
public MetaClass metaClassForProperty(String name) {
// 從類的反射器對象中找到對應(yīng)的類屬性的類型
Class<?> propType = reflector.getGetterType(name);
// 創(chuàng)建屬性對應(yīng)的MetaClass對象
return MetaClass.forClass(propType, reflectorFactory);
}
3、String findProperty(String name)
【功能】根據(jù)表達(dá)式分瘦,獲得屬性
【源碼與注解】
public String findProperty(String name) {
// 將表達(dá)式委托給 #buildProperty 方法處理
StringBuilder prop = buildProperty(name, new StringBuilder());
return prop.length() > 0 ? prop.toString() : null;
}
4蘸泻、StringBuilder buildProperty(String name, StringBuilder builder)
【功能】遞歸處理屬性表達(dá)式,并將處理結(jié)果返回給 #findProperty()
方法嘲玫。
【源碼與注解】
private StringBuilder buildProperty(String name, StringBuilder builder) {
PropertyTokenizer prop = new PropertyTokenizer(name); // 解析屬性表達(dá)式
// (1) 判斷是否有子表達(dá)式
if (prop.hasNext()) {
// (1.1) 查找 PropertyTokenizer.name 對應(yīng)的屬性
String propertyName = reflector.findPropertyName(prop.getName());
if (propertyName != null) {
builder.append(propertyName); // 追加屬性
builder.append(".");
// (1.2) 為該屬性創(chuàng)建對應(yīng)的MetaClass對象
MetaClass metaProp = metaClassForProperty(propertyName);
// (1.3) 遞歸解析 PropertyTokenizer.children 字段悦施,并將解析結(jié)果添加到 builder 中保存
metaProp.buildProperty(prop.getChildren(), builder);
}
} else {
// (2) 遞歸出口
String propertyName = reflector.findPropertyName(name);
if (propertyName != null) {
builder.append(propertyName);
}
}
return builder;
}
??比如屬性表達(dá)式 order[0].items[0].name
,第一次執(zhí)行方法時(shí)去团,解析到 propertyName 為 order抡诞,children 為 items[0].name
,遞歸調(diào)用土陪;第二次調(diào)用 propertyName 為 items昼汗,children 為 name
,遞歸調(diào)用鬼雀;第三次進(jìn)入遞歸出口分支顷窒,propertyName 為 name;所以最后返回的 builder 為 order.items.name取刃。
5蹋肮、String findProperty(String name, boolean useCamelCaseMapping)
【功能】在 #findProperty(String)
的基礎(chǔ)上增加了是否使用駝峰轉(zhuǎn)換的標(biāo)志位,如果屬性名是按照駝峰的規(guī)則璧疗,則先去除掉下劃線坯辩。
【源碼】
public String findProperty(String name, boolean useCamelCaseMapping) {
if (useCamelCaseMapping) {
name = name.replace("_", "");
}
return findProperty(name);
}
6、Class<?> getSetterType(String name)
【功能】獲取屬性表達(dá)式中的屬性對應(yīng) setter 方法的類型崩侠。
【源碼與注解】
public Class<?> getSetterType(String name) {
// 解析屬性表達(dá)式
PropertyTokenizer prop = new PropertyTokenizer(name);
// 判斷是否存在待處理的子表達(dá)式
if (prop.hasNext()) {
// 獲取頂層屬性對應(yīng)的 MetaClass 對象漆魔,遞歸調(diào)用
MetaClass metaProp = metaClassForProperty(prop.getName());
return metaProp.getSetterType(prop.getChildren());
} else {
// 不存在子表達(dá)式,直接根據(jù)屬性名從 reflector 中獲取屬性 setter 類型
return reflector.getSetterType(prop.getName());
}
}
7、Class<?> getGetterType(String name)
【功能】獲取屬性表達(dá)式中的屬性對應(yīng) getter 方法的類型改抡。
【源碼】
public Class<?> getGetterType(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
MetaClass metaProp = metaClassForProperty(prop);
return metaProp.getGetterType(prop.getChildren());
}
// issue #506. Resolve the type inside a Collection Object
return getGetterType(prop);
}
【解析】
??上面部分代碼的處理跟 #getSetterType()
方法的處理類似矢炼,當(dāng)解析到屬性表達(dá)式?jīng)]有子表達(dá)式時(shí),遞歸出口調(diào)用 #getGetterType(PropertyTokenizer)
方法處理阿纤,該方法主要用來處理要獲取的屬性是在集合中的情況如 order['id']
(但這里其實(shí)我也有點(diǎn)疑惑句灌,為什么 #getSetterType()
方法就不用這樣處理呢?)
8欠拾、Class<?> getGetterType(PropertyTokenizer prop)
【功能】解析帶泛型的 getterType 的真正類型
【源碼與注解】
private Class<?> getGetterType(PropertyTokenizer prop) {
// 獲取表達(dá)式中頂層屬性的類型
Class<?> type = reflector.getGetterType(prop.getName());
// 如果表達(dá)式中使用了下標(biāo)胰锌,并且頂層屬性的是 Collection 的子類
if (prop.getIndex() != null && Collection.class.isAssignableFrom(type)) {
// 通過 TypeParameterResolver 工具類解析屬性的類型
Type returnType = getGenericGetterType(prop.getName());
// 針對 ParameterizedType 進(jìn)行處理,即針對泛型集合類型進(jìn)行處理
if (returnType instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments(); // 獲取實(shí)際的類型參數(shù)
if (actualTypeArguments != null && actualTypeArguments.length == 1) { // 過濾掉多個(gè)實(shí)際參數(shù)類型的情況藐窄,是因?yàn)楸磉_(dá)式表示的屬性類型资昧,是對應(yīng)一個(gè)參數(shù)類型的集合
returnType = actualTypeArguments[0]; // 獲取泛型的類型
if (returnType instanceof Class) {
type = (Class<?>) returnType;
} else if (returnType instanceof ParameterizedType) {
type = (Class<?>) ((ParameterizedType) returnType).getRawType();
}
}
}
}
// 如果沒使用下標(biāo),或者解析完畢荆忍,返回對應(yīng)的類型
return type;
}
【解析】
??比如 order[0]
沒有子表達(dá)式格带,會(huì)調(diào)用本方法處理,假設(shè) order 屬性的類型為 List<String>刹枉,則 order[0]
表示列表中的第一個(gè)元素叽唱,其屬性類型應(yīng)為 String。
9微宝、Type getGenericGetterType(String propertyName)
【功能】獲取屬性對應(yīng)泛型類型中的泛型的具體類型
【源碼與注解】
private Type getGenericGetterType(String propertyName) {
try {
// 獲取屬性對應(yīng)的 getInvoker
Invoker invoker = reflector.getGetInvoker(propertyName);
// 如果 invoker 是一個(gè) MethodInvoker尔觉,即有對應(yīng) getter,獲取對應(yīng)的 Method
// 并調(diào)用 TypeParameterResolver.resolveReturnType 處理
if (invoker instanceof MethodInvoker) {
Field _method = MethodInvoker.class.getDeclaredField("method");
_method.setAccessible(true);
Method method = (Method) _method.get(invoker);
return TypeParameterResolver.resolveReturnType(method, reflector.getType());
// 如果 invoker 是一個(gè) GetFieldInvoker芥吟,即 invoker 中封裝的是一個(gè) Field,則獲取對應(yīng)的 Field
// 并調(diào)用 TypeParameterResolver.resolveFieldType 處理
} else if (invoker instanceof GetFieldInvoker) {
Field _field = GetFieldInvoker.class.getDeclaredField("field");
_field.setAccessible(true);
Field field = (Field) _field.get(invoker);
return TypeParameterResolver.resolveFieldType(field, reflector.getType());
}
} catch (NoSuchFieldException e) {
} catch (IllegalAccessException e) {
}
return null;
}
10专甩、MetaClass metaClassForProperty(PropertyTokenizer prop)
【功能】根據(jù)當(dāng)前類的一個(gè)屬性表達(dá)式钟鸵,創(chuàng)建表達(dá)式中表示的屬性對應(yīng)的 MetaClass 對象。
【源碼與注解】
private MetaClass metaClassForProperty(PropertyTokenizer prop) {
// 獲取表達(dá)式中屬性的真正類型
Class<?> propType = getGetterType(prop);
// 創(chuàng)建 MetaClass 對象
return MetaClass.forClass(propType, reflectorFactory);
}
11涤躲、boolean hasSetter(String name)
【功能】判斷表達(dá)式對應(yīng)的屬性是否允許設(shè)置值棺耍。
【源碼與注解】
public boolean hasSetter(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name); // 解析屬性表達(dá)式
if (prop.hasNext()) { // 判斷是否有子表達(dá)式
// 如果類中并沒有頂層屬性對應(yīng)的 setter,直接返回false种樱,若有則遞歸解析表達(dá)式并且遞歸調(diào)用本方法
if (reflector.hasSetter(prop.getName())) {
MetaClass metaProp = metaClassForProperty(prop.getName());
return metaProp.hasSetter(prop.getChildren());
} else {
return false;
}
} else {
// 如果沒有子表達(dá)式蒙袍,或者遞歸的出口,根據(jù)屬性名調(diào)用反射器的方法返回
return reflector.hasSetter(prop.getName());
}
}
12嫩挤、boolean hasGetter(String name)
【功能】判斷表達(dá)式對應(yīng)的屬性是否允許獲取值害幅。
【源碼與注解】跟 #hasSetter()
類型,不贅述岂昭。
public boolean hasGetter(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
if (reflector.hasGetter(prop.getName())) {
MetaClass metaProp = metaClassForProperty(prop);
return metaProp.hasGetter(prop.getChildren());
} else {
return false;
}
} else {
return reflector.hasGetter(prop.getName());
}
}
13以现、其他方法
【功能】代理調(diào)用 Reflector
的方法。
- (1)
#String[] getGetterNames()
:調(diào)用 reflector.getGetablePropertyNames() 獲取可讀屬性。 - (2)
#String[] getSetterNames()
:調(diào)用 reflector.getSetablePropertyNames() 獲取可寫屬性邑遏。 - (3)
#Invoker getGetInvoker(String name)
:調(diào)用 reflector.getGetInvoker(name) 獲取讀取屬性的調(diào)用器佣赖。 - (4)
#Invoker getSetInvoker(String name)
:調(diào)用 reflector.getSetInvoker(name) 獲取寫屬性的調(diào)用器。 - (5)
#boolean hasDefaultConstructor()
:調(diào)用 reflector.hasDefaultConstructor() 判斷類是否有默認(rèn)構(gòu)造方法记盒。
五憎蛤、測試案例
1、案例1
(1)類定義
// 泛型接口
public interface GenericInterface<K> {
void setId(K id);
}
// 泛型抽象類
public abstract class GenericAbstract<K> {
public abstract K getId();
}
// 繼承泛型抽象類并具體化類型的抽象類
public abstract class GenericSubclass extends GenericAbstract<Long> {
@Override
public abstract Long getId();
}
// 實(shí)現(xiàn)泛型接口和繼承泛型抽象類的類
public class GenericConcrete extends GenericSubclass implements GenericInterface<Long> {
private Long id;
@Override
public Long getId() {
return id;
}
public void setId(String id) {
this.id = Long.valueOf(id);
}
@Override
public void setId(Long id) {
this.id = id;
}
public void setId(Integer id) {
this.id = (long) id;
}
}
(2)測試代碼
@Test
public void shouldTestDataTypeOfGenericMethod() {
ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
MetaClass meta = MetaClass.forClass(GenericConcrete.class, reflectorFactory);
assertEquals(Long.class, meta.getGetterType("id"));
assertEquals(Long.class, meta.getSetterType("id"));
}
(3)執(zhí)行結(jié)果
2纪吮、案例2
(1)類定義
public class RichType {
private RichType richType;
private String richField;
private String richProperty;
private Map richMap = new HashMap();
private List richList = new ArrayList() {
{
add("bar");
}
};
public RichType getRichType() {
return richType;
}
public void setRichType(RichType richType) {
this.richType = richType;
}
public String getRichProperty() {
return richProperty;
}
public void setRichProperty(String richProperty) {
this.richProperty = richProperty;
}
public List getRichList() {
return richList;
}
public void setRichList(List richList) {
this.richList = richList;
}
public Map getRichMap() {
return richMap;
}
public void setRichMap(Map richMap) {
this.richMap = richMap;
}
}
(2)測試代碼
// 測試 hasGetter 方法
@Test
public void shouldCheckGetterExistance() {
ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
MetaClass meta = MetaClass.forClass(RichType.class, reflectorFactory);
assertTrue(meta.hasGetter("richField"));
assertTrue(meta.hasGetter("richProperty"));
assertTrue(meta.hasGetter("richList"));
assertTrue(meta.hasGetter("richMap"));
assertTrue(meta.hasGetter("richList[0]"));
assertTrue(meta.hasGetter("richType"));
assertTrue(meta.hasGetter("richType.richField"));
assertTrue(meta.hasGetter("richType.richProperty"));
assertTrue(meta.hasGetter("richType.richList"));
assertTrue(meta.hasGetter("richType.richMap"));
assertTrue(meta.hasGetter("richType.richList[0]"));
assertFalse(meta.hasGetter("[0]"));
}
// 測試 hasSetter 方法
@Test
public void shouldCheckSetterExistance() {
ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
MetaClass meta = MetaClass.forClass(RichType.class, reflectorFactory);
assertTrue(meta.hasSetter("richField"));
assertTrue(meta.hasSetter("richProperty"));
assertTrue(meta.hasSetter("richList"));
assertTrue(meta.hasSetter("richMap"));
assertTrue(meta.hasSetter("richList[0]"));
assertTrue(meta.hasSetter("richType"));
assertTrue(meta.hasSetter("richType.richField"));
assertTrue(meta.hasSetter("richType.richProperty"));
assertTrue(meta.hasSetter("richType.richList"));
assertTrue(meta.hasSetter("richType.richMap"));
assertTrue(meta.hasSetter("richType.richList[0]"));
assertFalse(meta.hasSetter("[0]"));
}
// 測試 getGetterType 方法
@Test
public void shouldCheckTypeForEachGetter() {
ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
MetaClass meta = MetaClass.forClass(RichType.class, reflectorFactory);
assertEquals(String.class, meta.getGetterType("richField"));
assertEquals(String.class, meta.getGetterType("richProperty"));
assertEquals(List.class, meta.getGetterType("richList"));
assertEquals(Map.class, meta.getGetterType("richMap"));
assertEquals(List.class, meta.getGetterType("richList[0]"));
assertEquals(RichType.class, meta.getGetterType("richType"));
assertEquals(String.class, meta.getGetterType("richType.richField"));
assertEquals(String.class, meta.getGetterType("richType.richProperty"));
assertEquals(List.class, meta.getGetterType("richType.richList"));
assertEquals(Map.class, meta.getGetterType("richType.richMap"));
assertEquals(List.class, meta.getGetterType("richType.richList[0]"));
}
// 測試 getSetterType 方法
@Test
public void shouldCheckTypeForEachSetter() {
ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
MetaClass meta = MetaClass.forClass(RichType.class, reflectorFactory);
assertEquals(String.class, meta.getSetterType("richField"));
assertEquals(String.class, meta.getSetterType("richProperty"));
assertEquals(List.class, meta.getSetterType("richList"));
assertEquals(Map.class, meta.getSetterType("richMap"));
assertEquals(List.class, meta.getSetterType("richList[0]"));
assertEquals(RichType.class, meta.getSetterType("richType"));
assertEquals(String.class, meta.getSetterType("richType.richField"));
assertEquals(String.class, meta.getSetterType("richType.richProperty"));
assertEquals(List.class, meta.getSetterType("richType.richList"));
assertEquals(Map.class, meta.getSetterType("richType.richMap"));
assertEquals(List.class, meta.getSetterType("richType.richList[0]"));
}
// 測試 getGetterNames 和 getSetterNames 方法
@Test
public void shouldCheckGetterAndSetterNames() {
ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
MetaClass meta = MetaClass.forClass(RichType.class, reflectorFactory);
assertEquals(5, meta.getGetterNames().length);
assertEquals(5, meta.getSetterNames().length);
}
// 測試 findProperty 方法
@Test
public void shouldFindPropertyName() {
ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
MetaClass meta = MetaClass.forClass(RichType.class, reflectorFactory);
assertEquals("richField", meta.findProperty("RICHfield"));
}
(3)執(zhí)行結(jié)果