Mybatis源码学习---(step-03)反射工具箱

一、问题汇总

1.mybatis的反射工具包结构以及各个组成的作用?
|--- reflection
     |--- factory
		  -I- ObjectFactory
		  --- DefaultObjectFactory
     |--- invoker
		  -I- Invoker
		  --- MethodInvoker
		  --- SetFieldInvoker
		  --- GetFieldInvoker
     |--- property
		  --- PropertyCopier
		  --- PropertyNamer
		  --- PropertyTokenizer
     |--- wrapper
     	  -I- ObjectWrapper
		  -A- BaseWrapper
		  --- BeanWrapper
		  --- MapWrapper
		  --- CollectionWrapper
		  -I- ObjectWrapperFactory
		  --- DefaultObjectWrapperFactory
     --- Reflector
     --- MetaClass
     --- MetaObject
     --- TypeParameterResolver
     --- SystemMetaObject
     --- ExceptionUtil
     --- ReflectionException
     -I- ReflectorFactory
     --- DefaultReflectorFactory

factory包:对象工厂包的作用是初始化对象实例,通过无参构造或者有参构造函数反射实例化对象,主要有create和isCollection方法,唯一实现类DefaultObjectFactory

invoker包:invoker是反射实体Method和field的包装类,它将method包装成MethodInvoker,invoke就是执行该方法。将可写的field包装成SetFieldInvoker,invoke方法执行赋值操作,有入参,将可读的field包装成GetFieldInvoker,invoke方法执行读取变量的操作,有返回值。

property包:这是一个属性工具包,PropertyCopier作用相当于BeanUtils.copy, PropertyNamer作用是根据set/get/is方法名获取字段名,例如:getName方法名对应的字段名为 name。 PropertyTokenizer专门用来解析 user[0].role[1].menu[0]这种类型的字符串。

wrapper包:这是一个对象包装工具包,顶层接口为ObjectWrapper定义了常用的方法(获取get/set属性名、获取属性get/set方法、get/set属性值、构建属性MetaObject对象…)BaseWrapper代表常规的key-value对象包装,子类有BeanWrapper和MapWrapper两个,在这层加了MetaObject对象、CollectionWrapper代表数组类型的对象包装,它只有add、addAll、isCollection三个可用方法。BeanWrapper中有MetaClass类元数据对象,MapWrapper中存放的Map<String, Object> map集合。

Reflector:类的元数据

Metaclass:Reflector基础上的一层封装,加上了PropertyTokenizer,可以通过(user.role.menu[index])的方式来获取层级中的元数据

MetaObject:对象的元数据

TypeParameterResolver:类型解析器

SystemMetaObjectr: SystemMetaObject.forObject创建MetaObject

ExceptionXxx:异常处理

ReflectorFactory:唯一实现类DefaultReflectorFactory.findForClass方法可以创建Reflector对象,默认开启缓存

2.反射工具包中有哪些类是核心类、有哪些核心方法?

Reflector:类的元数据,他是将一个类(一般为普通实体类)以反射的视角将它拆解开来待用,主要有以下几个属性

  // 用来初始化数组,优化内存
  private static final String[] EMPTY_STRING_ARRAY = new String[0];
  // 类的class对象
  private Class<?> type;
  // 所有get方法的属性集合 getMethods的key集合
  private String[] readablePropertyNames = EMPTY_STRING_ARRAY;
  // 所有set方法的属性集合 setMethods的key集合
  private String[] writeablePropertyNames = EMPTY_STRING_ARRAY;
  // set方法集合 name -> setName方法的MethodInvoker对象
  private Map<String, Invoker> setMethods = new HashMap<String, Invoker>();
  // get方法集合 name -> getName方法的MethodInvoker对象
  private Map<String, Invoker> getMethods = new HashMap<String, Invoker>();
  // set入参值类型 name -> String.class
  private Map<String, Class<?>> setTypes = new HashMap<String, Class<?>>();
  // get返回值类型 name -> String.class
  private Map<String, Class<?>> getTypes = new HashMap<String, Class<?>>();
  // 空参构造方法
  private Constructor<?> defaultConstructor;
  // 忽略大小写的map集合 NAME -> name
  private Map<String, String> caseInsensitivePropertyMap = new HashMap<String, String>();

所以Reflector对象的方法,大多也都是获取各种属性的方法

Metaclass:类的元数据,在Reflector的基础之上加了一层封装,在成员变量加上了ReflectorFactory,实现了Reflector的缓存,在部门方法上getSetterType等方法上添加了PropertyTokenizer工具类,实现了层级的对象属性查找

  // 用来缓存reflector对象
  private ReflectorFactory reflectorFactory;
  // 类元数据装载实体
  private Reflector reflector;
  
    // 获取属性的get方法返回值类型
  public Class<?> getGetterType(String name) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      MetaClass metaProp = metaClassForProperty(prop);
      return metaProp.getGetterType(prop.getChildren());
    }
    return getGetterType(prop);
  }

ObjectWrapper:对象包装器 ,接口核心功能如下

  Object get(PropertyTokenizer prop); // 获取值
  void set(PropertyTokenizer prop, Object value); // 设置值
  String findProperty(String name, boolean useCamelCaseMapping); 查找属性
  String[] getGetterNames(); // 有get方法的属性集合
  String[] getSetterNames(); // 有set方法的属性集合
  Class<?> getSetterType(String name); // 获取set方法
  Class<?> getGetterType(String name); // 获取get方法
  boolean hasSetter(String name); // 是否有set方法
  boolean hasGetter(String name); // 是否有get方法
  MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory); // 构造MetaObject
  boolean isCollection(); //isCollection  add addAll 针对的是Collection类型下的对象
  void add(Object element); // 添加
  <E> void addAll(List<E> element); // 添加所有

MetaObject:对象元数据,核心属性为originalObject原始对象和objectWrapper,其他的都是工厂类 ,核心方法是objectWrapper的方法,通过操纵objectWrapper的方法来实现自己的方法

  // 原始对象
  private Object originalObject;
  // 对象包装器
  private ObjectWrapper objectWrapper;
  // 对象工厂 单例
  private ObjectFactory objectFactory;
  // 对象包装器工厂 单例
  private ObjectWrapperFactory objectWrapperFactory;
  // 类元数据工厂 单例 + 缓存
  private ReflectorFactory reflectorFactory;
3.该包下有哪些惊叹的设计或者代码?

待补充…

4.说说MetaClass和MetaObject有什么关系?

metaclass和metaObject有什么关系,我弄了好久才弄懂。单从类名看很容易不清楚他们俩的关系,但是只要看看类里面的成员变量就知道了,他们俩没有直接的联系,但是,当MetaObject对象里的ObjectWrapper接口的实例是BaseWrapper(BeanWrapper或MapWrapper)的时候,会有成员变量MetaObject、在BeanWrapper中会有MetaClass变量。所以,MetaObject在对象不是Collection的情况下,是包含MetaClass对象的,也就是对象元数据在对象不是集合类型的时候是包含类元数据的。

在这里插入图片描述

5.说说MetaObject和ObjectWrapper的关系?

当MetaObject的成员变量ObjectWrapper的实例为BaseWrapper子类的情况下,他们俩是相互依存的关系,互相将该对象地址指向对方。否则,没有半毛钱关系。
请添加图片描述

请添加图片描述

6.一个实体类在反射包中的赋值流程、详细到类和方法?

以MetaObject object = SystemMetaObject.forObject(new User())为例来讲解步骤

1.进入SystemMetaObject.forObject静态方法,该类有很多默认成员变量,大多都是static new 出来的

2.进入MetaObject.forObject方法,此方法内部采用 new MetaObject(User对象,各种工厂实例) 的方式调用构造函数

3.进入构造函数给成员变量直接赋值,唯有Objectwrapper需要构造,最后一步是通过new XxxWrapper()方式给它赋值

4.因为User属于普通的Bean对象,程序会进入new BeanWrapper(this, object)初始化并赋值,此时的this代表本类对象

5.BeanWrapper初始化时成员变量有三个分别是object,metaObject,metaClass,其中前两个根据入参直接赋值,MetaClass通过MetaClass.forClass(Object,ReflectorFactory)构造MetaClass

6.MetaClass内部有Object和Reflector对象,其中Reflector对象需要实例化,内部是通过reflectorFactory.findForClass(Object)方式,最终是new Reflector(class)实例化Reflector对象

7.通过反射的方式获取set/get方法集合,set/get属性,set入参类型、get返回值类型元数据,初始化Reflector对象并返回,链式返回则初始化了整个MetaObject对象

二、重点补充

1.待补充…
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值