[MyBatis源码分析 - 反射器模块 - 组件六] Meta
一、简介
MetaClass
通过对 Reflector
和 PropertyTokenizer
组合使用,实现了对复杂的属性表达式的解析,并实现了获取指定属性描述信息的功能。
二、成员属性
private ReflectorFactory reflectorFactory;
private Reflector reflector;
-
reflectorFactory
:负责创建和缓存 Reflector 对象的工厂类。 -
reflector
:传入的 Class 对象对应的 Reflector 对象,该对象保存了该类相关的元信息。
三、构造方法
// 构造方法,被静态方法#forClass内部调用
private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
this.reflectorFactory = reflectorFactory;
this.reflector = reflectorFactory.findForClass(type);
}
这是一个私有构造方法,构造函数会被静态内部类 #forClass()
调用。
四、方法功能
1、MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory)
【功能】创建指定类的 MetaClass 对象(创建 Reflector 对象的工厂对象可以用户指定)。
【源码与注解】
// 根据传入的Class对象和反射工厂对象创建对应的MetaClass对象
public static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) {
return new MetaClass(type, reflectorFactory);
}
2、MetaClass metaClassForProperty(String name)
【功能】根据指定的类属性名创建类属性类型对应的MataClass对象。
【源码与注解】
// 根据类属性名创建类属性类型对应的MataClass对象
public MetaClass metaClassForProperty(String name) {
// 从类的反射器对象中找到对应的类属性的类型
Class<?> propType = reflector.getGetterType(name);
// 创建属性对应的MetaClass对象
return MetaClass.forClass(propType, reflectorFactory);
}
3、String findProperty(String name)
【功能】根据表达式,获得属性
【源码与注解】
public String findProperty(String name) {
// 将表达式委托给 #buildProperty 方法处理
StringBuilder prop = buildProperty(name, new StringBuilder());
return prop.length() > 0 ? prop.toString() : null;
}
4、StringBuilder buildProperty(String name, StringBuilder builder)
【功能】递归处理属性表达式,并将处理结果返回给 #findProperty()
方法。
【源码与注解】
private StringBuilder buildProperty(String name, StringBuilder builder) {
PropertyTokenizer prop = new PropertyTokenizer(name); // 解析属性表达式
// (1) 判断是否有子表达式
if (prop.hasNext()) {
// (1.1) 查找 PropertyTokenizer.name 对应的属性
String propertyName = reflector.findPropertyName(prop.getName());
if (propertyName != null) {
builder.append(propertyName); // 追加属性
builder.append(".");
// (1.2) 为该属性创建对应的MetaClass对象
MetaClass metaProp = metaClassForProperty(propertyName);
// (1.3) 递归解析 PropertyTokenizer.children 字段,并将解析结果添加到 builder 中保存
metaProp.buildProperty(prop.getChildren(), builder);
}
} else {
// (2) 递归出口
String propertyName = reflector.findPropertyName(name);
if (propertyName != null) {
builder.append(propertyName);
}
}
return builder;
}
比如属性表达式 order[0].items[0].name
,第一次执行方法时,解析到 propertyName 为 order,children 为 items[0].name
,递归调用;第二次调用 propertyName 为 items,children 为 name
,递归调用;第三次进入递归出口分支,propertyName 为 name;所以最后返回的 builder 为 order.items.name。
5、String findProperty(String name, boolean useCamelCaseMapping)
【功能】在 #findProperty(String)
的基础上增加了是否使用驼峰转换的标志位,如果属性名是按照驼峰的规则,则先去除掉下划线。
【源码】
public String findProperty(String name, boolean useCamelCaseMapping) {
if (useCamelCaseMapping) {
name = name.replace("_", "");
}
return findProperty(name);
}
6、Class<?> getSetterType(String name)
【功能】获取属性表达式中的属性对应 setter 方法的类型。
【源码与注解】
public Class<?> getSetterType(String name) {
// 解析属性表达式
PropertyTokenizer prop = new PropertyTokenizer(name);
// 判断是否存在待处理的子表达式
if (prop.hasNext()) {
// 获取顶层属性对应的 MetaClass 对象,递归调用
MetaClass metaProp = metaClassForProperty(prop.getName());
return metaProp.getSetterType(prop.getChildren());
} else {
// 不存在子表达式,直接根据属性名从 reflector 中获取属性 setter 类型
return reflector.getSetterType(prop.getName());
}
}
7、Class<?> getGetterType(String name)
【功能】获取属性表达式中的属性对应 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()
方法的处理类似,当解析到属性表达式没有子表达式时,递归出口调用 #getGetterType(PropertyTokenizer)
方法处理,该方法主要用来处理要获取的属性是在集合中的情况如 order['id']
(但这里其实我也有点疑惑,为什么 #getSetterType()
方法就不用这样处理呢?)
8、Class<?> getGetterType(PropertyTokenizer prop)
【功能】解析带泛型的 getterType 的真正类型
【源码与注解】
private Class<?> getGetterType(PropertyTokenizer prop) {
// 获取表达式中顶层属性的类型
Class<?> type = reflector.getGetterType(prop.getName());
// 如果表达式中使用了下标,并且顶层属性的是 Collection 的子类
if (prop.getIndex() != null && Collection.class.isAssignableFrom(type)) {
// 通过 TypeParameterResolver 工具类解析属性的类型
Type returnType = getGenericGetterType(prop.getName());
// 针对 ParameterizedType 进行处理,即针对泛型集合类型进行处理
if (returnType instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments(); // 获取实际的类型参数
if (actualTypeArguments != null && actualTypeArguments.length == 1) { // 过滤掉多个实际参数类型的情况,是因为表达式表示的属性类型,是对应一个参数类型的集合
returnType = actualTypeArguments[0]; // 获取泛型的类型
if (returnType instanceof Class) {
type = (Class<?>) returnType;
} else if (returnType instanceof ParameterizedType) {
type = (Class<?>) ((ParameterizedType) returnType).getRawType();
}
}
}
}
// 如果没使用下标,或者解析完毕,返回对应的类型
return type;
}
【解析】
比如 order[0]
没有子表达式,会调用本方法处理,假设 order 属性的类型为 List<String>,则 order[0]
表示列表中的第一个元素,其属性类型应为 String。
9、Type getGenericGetterType(String propertyName)
【功能】获取属性对应泛型类型中的泛型的具体类型
【源码与注解】
private Type getGenericGetterType(String propertyName) {
try {
// 获取属性对应的 getInvoker
Invoker invoker = reflector.getGetInvoker(propertyName);
// 如果 invoker 是一个 MethodInvoker,即有对应 getter,获取对应的 Method
// 并调用 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 是一个 GetFieldInvoker,即 invoker 中封装的是一个 Field,则获取对应的 Field
// 并调用 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)
【功能】根据当前类的一个属性表达式,创建表达式中表示的属性对应的 MetaClass 对象。
【源码与注解】
private MetaClass metaClassForProperty(PropertyTokenizer prop) {
// 获取表达式中属性的真正类型
Class<?> propType = getGetterType(prop);
// 创建 MetaClass 对象
return MetaClass.forClass(propType, reflectorFactory);
}
11、boolean hasSetter(String name)
【功能】判断表达式对应的属性是否允许设置值。
【源码与注解】
public boolean hasSetter(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name); // 解析属性表达式
if (prop.hasNext()) { // 判断是否有子表达式
// 如果类中并没有顶层属性对应的 setter,直接返回false,若有则递归解析表达式并且递归调用本方法
if (reflector.hasSetter(prop.getName())) {
MetaClass metaProp = metaClassForProperty(prop.getName());
return metaProp.hasSetter(prop.getChildren());
} else {
return false;
}
} else {
// 如果没有子表达式,或者递归的出口,根据属性名调用反射器的方法返回
return reflector.hasSetter(prop.getName());
}
}
12、boolean hasGetter(String name)
【功能】判断表达式对应的属性是否允许获取值。
【源码与注解】跟 #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、其他方法
【功能】代理调用 Reflector
的方法。
- (1)
#String[] getGetterNames()
:调用 reflector.getGetablePropertyNames() 获取可读属性。 - (2)
#String[] getSetterNames()
:调用 reflector.getSetablePropertyNames() 获取可写属性。 - (3)
#Invoker getGetInvoker(String name)
:调用 reflector.getGetInvoker(name) 获取读取属性的调用器。 - (4)
#Invoker getSetInvoker(String name)
:调用 reflector.getSetInvoker(name) 获取写属性的调用器。 - (5)
#boolean hasDefaultConstructor()
:调用 reflector.hasDefaultConstructor() 判断类是否有默认构造方法。
五、测试案例
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();
}
// 实现泛型接口和继承泛型抽象类的类
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)执行结果

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)执行结果
