Mybatis框架基础支持层——反射工具箱之MetaClass(7)
简介:MetaClass是Mybatis对类级别的元信息的封装和处理,通过与属性工具类的结合, 实现了对复杂表达式的解析,实现了获取指定描述信息的功能
- public class MetaClass {
- private ReflectorFactory reflectorFactory;
- private Reflector reflector;
- /**
- * 构造函数私有
- */
- private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
- this.reflectorFactory = reflectorFactory;
- this.reflector = reflectorFactory.findForClass(type);
- }
- /**
- * 调用构造方法创建MetaClass
- */
- public static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) {
- return new MetaClass(type, reflectorFactory);
- }
- /**
- * 通过属性名称, 获取属性的MetaClass(解决成员变量是类的情况)
- */
- public MetaClass metaClassForProperty(String name) {
- Class<?> propType = reflector.getGetterType(name);
- return MetaClass.forClass(propType, reflectorFactory);
- }
- public String findProperty(String name) {
- StringBuilder prop = buildProperty(name, new StringBuilder());
- return prop.length() > ? 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 == ) {
- returnType = actualTypeArguments[];
- 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 e) {
- } catch (IllegalAccessException e) {
- }
- 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);
- }
- /**
- * 解析属性表达式 会去寻找reflector中是否有对应的的属性
- */
- private StringBuilder buildProperty(String name, StringBuilder builder) {
- // 解析属性表达式
- PropertyTokenizer prop = new PropertyTokenizer(name);
- // 是否有子表达式
- if (prop.hasNext()) {
- // 查找对应的属性
- String propertyName = reflector.findPropertyName(prop.getName());
- if (propertyName != null) {
- // 追加属性名
- builder.append(propertyName);
- builder.append(".");
- // 创建对应的 MetaClass 对象
- MetaClass metaProp = metaClassForProperty(propertyName);
- // 解析子表达式, 递归
- metaProp.buildProperty(prop.getChildren(), builder);
- }
- } else {
- // 根据名称查找属性
- String propertyName = reflector.findPropertyName(name);
- if (propertyName != null) {
- builder.append(propertyName);
- }
- }
- return builder;
- }
- public boolean hasDefaultConstructor() {
- return reflector.hasDefaultConstructor();
- }
- }
理解了这个方法(递归, 该类中有很多类似的), 就可以很好的对这个类进行理解, 以查找(richType.richProperty)为例:
- 通过 PropertyTokenizer 对表达式进行解析, 得到当前的 name = richType, children = richProperty
- 从 reflector 中查找该 richType 属性
- 将 richType 添加到 builder 中
- 使用 metaClassForProperty 创建 richType 的 MetaClass。
- 递归调用自身来处理子表达式
退出的条件就是没有子表达式。 这个就是为了, 我们类中有成员变量是类, 我们可以通过其找到他们的所有类及其属性。
注意, 在此过程中, ReflectorFactory 一直是同一个, 而其内部缓存了多个 Reflector 对象。
Mybatis框架基础支持层——反射工具箱之MetaClass(7)的更多相关文章
- Mybatis框架基础支持层——反射工具箱之Reflector&ReflectorFactory(3)
说明:Reflector是Mybatis反射工具的基础,每个Reflector对应一个类,在Reflector中封装有该类的元信息, 以及基于类信息的一系列反射应用封装API public class ...
- Mybatis框架基础支持层——反射工具箱之实体属性Property工具集(6)
本篇主要介绍mybatis反射工具中用到的三个属性工具类:PropertyTokenizer.PropertyNamer.PropertyCopier. PropertyTokenizer: 主要用来 ...
- Mybatis框架基础支持层——反射工具箱之对象工厂ObjectFactory&DefaultObjectFactory(5)
ObjectFactory官方简介:MyBatis每次创建结果集对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成. 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认 ...
- Mybatis框架基础支持层——反射工具箱之泛型解析工具TypeParameterResolver(4)
简介:TypeParameterResolver是一个工具类,提供一系列的静态方法,去解析类中的字段.方法返回值.方法参数的类型. 在正式介绍TypeParameterResolver之前,先介绍一个 ...
- Mybatis框架基础支持层——日志模块(8)
前言: java开发中常用的日志框架有Log4j,Log4j2,Apache Commons Log,java.util.logging,slf4j等,这些工具对外的接口不尽相同.为了统一这些工具的接 ...
- Mybatis框架基础支持层——解析器模块(2)
解析器模块,核心类XPathParser /** * 封装了用于xml解析的类XPath.Document和EntityResolver */ public class XPathParser { / ...
- MyBatis源码分析-基础支持层反射模块Reflector/ReflectorFactory
本文主要介绍MyBatis的反射模块是如何实现的. MyBatis 反射的核心类Reflector,下面我先说明它的构造函数和成员变量.具体方法下面详解. org.apache.ibatis.refl ...
- 精尽 MyBatis 源码分析 - 基础支持层
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- MyBatis 框架 基础应用
1.ORM的概念和优势 概念: 对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据 ...
随机推荐
- C#线程的使用(1)
今天刚开始学习使用线程,把学习过程与新的记录下来. 创建线程: 非常简单,只需声明她并为其提供线程起始点处的方法委托即可: 终止线程: 使用Abort和Join方法来实现: Abort方法:用于永久的 ...
- [微信小程序]在应用地图时,如何设置满屏(高度)
微信小程序在做地图功能时 用常规的办法height:100%:来设置高度来占满屏幕是不行的 它不会生效 应该改用单位vh 例如 height:100vh 这样就可以是地图占满整个屏幕高度
- 有关promise的技巧
其实promise的作用是将异步的代码转化为同步,这里的异步指的是request1,request2.
- c# 钩子类
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using S ...
- 流媒体协议(二):RTMP协议
一.概念与摘要 RTMP协议从属于应用层,被设计用来在适合的传输协议(如TCP)上复用和打包多媒体传输流(如音频.视频和互动内容).RTMP提供了一套全双工的可靠的多路复用消息服务,类似于TCP协议[ ...
- 51Nod-1006 最长公共子序列Lcs
题目链接 Description 给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdkscab ab是两个串的子序列,abc也是,abca ...
- JVM内存知识备忘
又是一篇备忘... 主要记录一些知识,进行一些资源的汇总. 先来群里liufor大大提供的两张图,清晰易懂: Dockerized Java https://www.youtube.com/watch ...
- Java:多态乃幸福本源
01 多态是什么 在我刻板的印象里,西游记里的那段孙悟空和二郎神的精彩对战就能很好的解释“多态”这个词:一个孙悟空,能七十二变:一个二郎神,也能七十二变:他们都可以变成不同的形态,但只需要悄悄地喊一声 ...
- Java面试题:小白不得不懂的斐波那契数列
很长一段时间里,我都非常疑惑:“我写的技术文章不差啊,有内容的同时还很有趣,不至于每篇只有区区几十个人读啊?为什么有些内容简单到只有一行注册码的文章浏览量反而轻松破万?”这样的疑惑如鲠在喉啊!写技术博 ...
- Centos 7 .Net core后台守护进程Supervisor配置
环境: Centos 7 已安装.Net core 2.0.0 .Net core 1.1.2 1.Supervisor安装 yum 安装 yum install supervisor (阿里云验证 ...