文章目录
1. Reflector
官方介绍:This class represents a cached set of class definition information that allows for easy mapping between property names and getter/setter methods.
Reflector是反射模块的基础,缓存了类所有的元信息。
1.1 属性
// 对应的Class 类型 1
private final Class<?> type;
// 可读属性的名称集合 可读属性就是存在 getter方法的属性,初始值为null
private final String[] readablePropertyNames;
// 可写属性的名称集合 可写属性就是存在 setter方法的属性,初始值为null
private final String[] writablePropertyNames;
// 记录了属性相应的setter方法,key是属性名称,value是Invoker方法
// 他是对setter方法对应Method对象的封装
private final Map<String, Invoker> setMethods = new HashMap<>();
// 属性相应的getter方法
private final Map<String, Invoker> getMethods = new HashMap<>();
// 记录了相应setter方法的参数类型,key是属性名称 value是setter方法的参数类型
private final Map<String, Class<?>> setTypes = new HashMap<>();
// 和上面的对应
private final Map<String, Class<?>> getTypes = new HashMap<>();
// 记录了默认的构造方法
private Constructor<?> defaultConstructor;
// 记录了所有属性名称的集合
private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();
1.2 构造函数
// 解析指定的Class类型 并填充上述的集合信息
public Reflector(Class<?> clazz) {
type = clazz; // 初始化 type字段
addDefaultConstructor(clazz);// 设置默认的构造方法
addGetMethods(clazz);// 获取getter方法
addSetMethods(clazz); // 获取setter方法
addFields(clazz); // 处理没有getter/setter方法的字段 会将这些字段 添加对应的 getter/setter 方法
// 初始化 可读属性名称集合
readablePropertyNames = getMethods.keySet().toArray(new String[0]);
// 初始化 可写属性名称集合
writablePropertyNames = setMethods.keySet().toArray(new String[0]);
// caseInsensitivePropertyMap记录了所有的可读和可写属性的名称 也就是记录了所有的属性名称
for (String propName : readablePropertyNames) {
// 属性名称转大写
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
for (String propName : writablePropertyNames) {
// 属性名称转大写
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
}
1.3 api汇总
方法名称 | 作用 |
---|---|
getType | 获取Reflector表示的Class |
getDefaultConstructor | 获取默认的构造器 |
hasDefaultConstructor | 判断是否有默认的构造器 |
getSetInvoker | 根据属性名称获取对应的Invoker 对象 |
getGetInvoker | 根据属性名称获取对应的Invoker对象 |
getSetterType | 获取属性对应的类型 比如: String name; // getSetterType(“name”) --> java.lang.String |
getGetterType | 与上面是对应的 |
getGetablePropertyNames | 获取所有的可读属性名称的集合 |
getSetablePropertyNames | 获取所有的可写属性名称的集合 |
hasSetter | 判断是否具有某个可写的属性 |
hasGetter | 判断是否具有某个可读的属性 |
findPropertyName | 根据名称查找属性 |
2. ReflectorFactory
ReflectorFactory主要实现对Reflector的创建和缓存。
2.1 ReflectorFactory接口定义
public interface ReflectorFactory {
// 检测该ReflectorFactory是否缓存了Reflector对象
boolean isClassCacheEnabled();
// 设置是否缓存Reflector对象
void setClassCacheEnabled(boolean classCacheEnabled);
// 创建指定了Class的Reflector对象
Reflector findForClass(Class<?> type);
}
2.2 DefaultReflectorFactory
public class DefaultReflectorFactory implements ReflectorFactory {
// 决定是否开启缓存
private boolean classCacheEnabled = true;
// 实现对 Reflector 对象的缓存
private final ConcurrentMap<Class<?>, Reflector> reflectorMap = new ConcurrentHashMap<>();
public DefaultReflectorFactory() {
}
@Override
public boolean isClassCacheEnabled() {
return classCacheEnabled;
}
@Override
public void setClassCacheEnabled(boolean classCacheEnabled) {
this.classCacheEnabled = classCacheEnabled;
}
@Override
public Reflector findForClass(Class<?> type) {
if (classCacheEnabled) {// 开启缓存
// 如果reflectorMap中没有type类型的Reflector对象
// 则创建Reflector对象并存储在reflectorMap中
return reflectorMap.computeIfAbsent(type, Reflector::new);
} else {
// 没有开启缓存就直接创建
return new Reflector(type);
}
}
}
3. Invoker
针对于Class中Field和Method的调用,在MyBatis中封装了Invoker对象来统一处理(使用到适配器模式)
3.1 接口
public interface Invoker {
// 执行Field或者Method
Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;
// 返回属性相应的类型
Class<?> getType();
}
3.2 接口实习
3.3 使用效果
public class Student {
public Integer getId() {
System.out.println("读取id");
return 6;
}
public void setId(Integer id) {
System.out.println("写入id:"+id);
}
public String getUserName() {
return "张三";
}
}
public void test03() throws Exception{
ReflectorFactory factory = new DefaultReflectorFactory();
Reflector reflector = factory.findForClass(Student.class);
// 获取构造器 生成对应的对象
Object o = reflector.getDefaultConstructor().newInstance();
MethodInvoker invoker1 = (MethodInvoker) reflector.getSetInvoker("id");
invoker1.invoke(o,new Object[]{999});
// 读取
Invoker invoker2 = reflector.getGetInvoker("id");
invoker2.invoke(o,null);
}
4.ObjectFactory
ObjectFactory是创建对象的工厂,默认实现DefaultObjectFactory 。ObjectFactory提供了两个create()来创建对象。这个可以自定义自己的实现,并在 mybatis-config.xml 配置文件配置。
5. 属性解析工具
- PropertyTokenizer 工具类负责解析由“.”和“[]”构成的表达式。PropertyTokenizer 继承了 Iterator 接口,可以迭代处理嵌套多层表达式。
- PropertyCopier 是一个属性拷贝的工具类,提供了与 Spring 中 BeanUtils.copyProperties() 类似的功能,实现相同类型的两个对象之间的属性值拷贝,其核心方法是 copyBeanProperties() 方法。
- PropertyNamer 工具类提供的功能是转换方法名到属性名,以及检测一个方法名是否为 getter 或 setter 方法。
6.MetaClass
Class的元信息。
在Reflector中可以针对普通的属性操作,但是如果出现了比较复杂的属性,比如 private Person person; 这种,我们要查找的表达式 person.userName.针对这种表达式的处理,这时就可以通过MetaClass来处理了。
MetaClass 中的 findProperty() 方法是实现属性查找的核心方法,它主要处理了“.”导航的属性查找,该方法会用前文介绍的 PropertyTokenizer 解析传入的 name 表达式,该表达式可能通过“.”导航多层,例如,order.deliveryAddress.customer.name。
MetaClass 会逐层处理这个表达式,首先通过 Order 类型对应的 Reflector 查找 deliveryAddress 属性,查找成功之后,根据 deliveryAddress 属性的类型(即 Address 类型)创建对应的 MetaClass 对象(以及底层的 Reflector 对象),再继续查找其中的 customer 属性,如此递归处理,直至最后查找到 Customer 中的 name 属性。这部分递归查找逻辑位于 MetaClass.buildProperty() 方法中。
6.1 代码
/**
* 通过 Reflector 和 ReflectorFactory 的组合使用 实现对复杂的属性表达式的解析
* public class User{
* public Order Obj.order;
* }
* @author Clinton Begin
*/
public class MetaClass {
// 缓存 Reflector
private final ReflectorFactory reflectorFactory;
// 创建 MetaClass时 会指定一个Class reflector会记录该类的相关信息
private final Reflector reflector;
private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
this.reflectorFactory = reflectorFactory;
this.reflector = reflectorFactory.findForClass(type);
}
public static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) {
return new MetaClass(type, reflectorFactory);
}
/**
* 根据方法名称获取返回的类型 Person getPerson()
* metaClassForProperty("person") --》 Person
*/
public MetaClass metaClassForProperty(String name) {
// orders 查找属性对应的 Class 类型
Class<?> propType = reflector.getGetterType(name);
// 为该属性创建对应的 MetaClass 对象
return MetaClass.forClass(propType, reflectorFactory);
}
public String findProperty(String name) {
StringBuilder prop = buildProperty(name, new StringBuilder());
return prop.length() > 0 ? prop.toString() : null;
}
public String findProperty(String name, boolean useCamelCaseMapping) {
if (useCamelCaseMapping) {
name = name.replace("_", "");
}
return findProperty(name);
}
public String[] getGetterNames() {
return reflector.getGetablePropertyNames();
}
public String[] getSetterNames() {
return reflector.getSetablePropertyNames();
}
public Class<?> getSetterType(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
MetaClass metaProp = metaClassForProperty(prop.getName());
return metaProp.getSetterType(prop.getChildren());
} else {
return reflector.getSetterType(prop.getName());
}
}
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);
}
private MetaClass metaClassForProperty(PropertyTokenizer prop) {
Class<?> propType = getGetterType(prop);
return MetaClass.forClass(propType, reflectorFactory);
}
private Class<?> getGetterType(PropertyTokenizer prop) {
Class<?> type = reflector.getGetterType(prop.getName());
if (prop.getIndex() != null && Collection.class.isAssignableFrom(type)) {
Type returnType = getGenericGetterType(prop.getName());
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;
}
private Type getGenericGetterType(String propertyName) {
try {
Invoker invoker = reflector.getGetInvoker(propertyName);
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());
} 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 | IllegalAccessException ignored) {
}
return null;
}
public boolean hasSetter(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
if (reflector.hasSetter(prop.getName())) {
MetaClass metaProp = metaClassForProperty(prop.getName());
return metaProp.hasSetter(prop.getChildren());
} else {
return false;
}
} else {
return reflector.hasSetter(prop.getName());
}
}
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());
}
}
public Invoker getGetInvoker(String name) {
return reflector.getGetInvoker(name);
}
public Invoker getSetInvoker(String name) {
return reflector.getSetInvoker(name);
}
private StringBuilder buildProperty(String name, StringBuilder builder) {
PropertyTokenizer prop = new PropertyTokenizer(name);// 解析属性表达式 orders[0].items[0].name
if (prop.hasNext()) { // 判断是否有子表达式 name=orders index=0 indexedName=orders[0]
String propertyName = reflector.findPropertyName(prop.getName());
if (propertyName != null) {
builder.append(propertyName);
builder.append("."); // orders.
MetaClass metaProp = metaClassForProperty(propertyName); // orders --> 对应的类型
metaProp.buildProperty(prop.getChildren(), builder); // 递归处理 并将结果保存到 builder 中
}
} else { // 递归的出口
String propertyName = reflector.findPropertyName(name);
if (propertyName != null) {
builder.append(propertyName);
}
}
return builder;
}
public boolean hasDefaultConstructor() {
return reflector.hasDefaultConstructor();
}
}
6.2 效果演示
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;
}
}
@Test
public void test7(){
ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
MetaClass meta = MetaClass.forClass(RichType.class, reflectorFactory);
System.out.println(meta.hasGetter("richField"));
System.out.println(meta.hasGetter("richProperty"));
System.out.println(meta.hasGetter("richList"));
System.out.println(meta.hasGetter("richMap"));
System.out.println(meta.hasGetter("richList[0]"));
System.out.println(meta.hasGetter("richType"));
System.out.println(meta.hasGetter("richType.richField"));
System.out.println(meta.hasGetter("richType.richProperty"));
System.out.println(meta.hasGetter("richType.richList"));
System.out.println(meta.hasGetter("richType.richMap"));
System.out.println(meta.hasGetter("richType.richList[0]"));
// findProperty 只能处理 . 的表达式
System.out.println(meta.findProperty("richType.richProperty"));
System.out.println(meta.findProperty("richType.richProperty1"));
System.out.println(meta.findProperty("richList[0]"));
System.out.println(Arrays.toString(meta.getGetterNames()));
}
true
true
true
true
true
true
true
true
true
true
true
richType.richProperty
richType.
null
[richType, richProperty, richMap, richList, richField]
7.ObjectWrapper
MetaClass 中封装的是 Class 元信息,ObjectWrapper 封装的则是对象元信息。
在 ObjectWrapper 中抽象了一个对象的属性信息,并提供了查询对象属性信息的相关方法,以及更新属性值的相关方法。
8. MetaObject
可以通过MetaObject对象解析复杂的表达式来对提供的对象进行操作。
@Test
public void shouldGetAndSetField() {
RichType rich = new RichType();
MetaObject meta = SystemMetaObject.forObject(rich);
meta.setValue("richField", "foo");
System.out.println(meta.getValue("richField"));
}
@Test
public void shouldGetAndSetNestedField() {
RichType rich = new RichType();
MetaObject meta = SystemMetaObject.forObject(rich);
meta.setValue("richType.richField", "foo");
System.out.println(meta.getValue("richType.richField"));
}
@Test
public void shouldGetAndSetMapPairUsingArraySyntax() {
RichType rich = new RichType();
MetaObject meta = SystemMetaObject.forObject(rich);
meta.setValue("richMap[key]", "foo");
System.out.println(meta.getValue("richMap[key]"));
}
以上三个方法的输出结果都是:foo。
6. 反射应用
6.1 Configuration
解析全局配置文件,创建Configuration对象的时候,默认创建ReflectorFactory。