做矿业的郑州公司网站,做百度手机网站优化快,大宗商品交易平台招商,建筑公司简介模板范文文章目录 一、目标#xff1a;元对象反射类二、设计#xff1a;元对象反射类三、实现#xff1a;元对象反射类3.1 工程结构3.2 元对象反射类关系图3.3 反射调用者3.3.1 统一调用者接口3.3.2 方法调用者3.3.3 getter 调用者3.3.4 setter 调用者 3.4 属性命名和分解标记3.4.1 … 文章目录 一、目标元对象反射类二、设计元对象反射类三、实现元对象反射类3.1 工程结构3.2 元对象反射类关系图3.3 反射调用者3.3.1 统一调用者接口3.3.2 方法调用者3.3.3 getter 调用者3.3.4 setter 调用者 3.4 属性命名和分解标记3.4.1 属性命名器3.4.2 属性分解标记 3.5 反射器解耦对象3.6 元类包装反射器3.7 对象包装器 Wrapper3.7.1 对象包装器接口3.7.2 对象包装器抽象基类3.7.3 Bean 包装器3.7.4 Collection 包装器3.7.5 MapWrapper 包装器 3.8 对象包装工厂3.8.1 对象包装工厂接口3.8.2 默认对象包装工厂实现类 3.9 对象工厂3.9.1 对象工厂接口3.9.2 默认对象工厂实现类 3.10 元对象封装3.10.1 元对象3.10.2 系统级别元对象 3.11 数据源属性设置3.11.1 无池化数据源工厂3.11.2 有池化数据源工厂 四、测试元对象反射类4.1 单元测试4.2 反射类测试4.2.1 学生实体类4.2.2 老师实体类4.2.3 反射类测试 五、总结元对象反射类 一、目标元对象反射类 在实现数据源池化时对于属性信息的获取采用硬编码的方式。如何采取更好的方式呢 在数据源获取属性信息时也就是通过 props.getproperty(driver) 等属性都是通过手动编码的方式获取的。但是扩展性极差。如何增强扩张性呢。 Mybatis 的源码在这里使用了 Mybatis 自己实现的元对象反射工具类可以完成一个对象的属性的反射填充。MetaObject 元对象反射工具类 元对象、对象包装器、对象工厂、对象包装工厂、Reflector 反射器
二、设计元对象反射类 什么是元对象反射工具类 当需要对一个对象的所提供的属性进行统一的设置和获取值的操作。需要把当前这个被处理的对象解耦提取出它所有的属性和方法并按照不同的类型进行反射处理从而包装成一个工具包。 整个设计过程都围绕 如何拆解对象并提供反射操作 为主。 对于一个对象来说它所包括的有对象的构造函数、对象的属性、对象的方法。而对象的方法因为都是获取和设置值的操作所以基本都是 get/set 处理所以需要把这些方法在对象拆解的过程中摘取出来进行保存。 当真正的开始操作时则会依赖于已经实例化的对象对其进行属性处理。 而这些处理过程实际都是使用 JDK 所提供的 反射 进行操作的。而反射过程中的方法名称、入参类型都已经被我们拆解和处理了最终使用的时候直接调用即可。
三、实现元对象反射类
3.1 工程结构
mybatis-step-07
|-src|-main| |-java| |-com.lino.mybatis| |-binding| | |-MapperMethod.java| | |-MapperProxy.java| | |-MapperProxyFactory.java| | |-MapperRegistry.java| |-builder| | |-xml| | | |-XMLConfigBuilder.java| | |-BaseBuilder.java| |-datasource| | |-druid| | | |-DruidDataSourceFacroty.java| | |-pooled| | | |-PooledConnection.java| | | |-PooledDataSource.java| | | |-PooledDataSourceFacroty.java| | | |-PoolState.java| | |-unpooled| | | |-UnpooledDataSource.java| | | |-UnpooledDataSourceFacroty.java| | |-DataSourceFactory.java| |-executor| | |-resultset| | | |-DefaultResultSetHandler.java| | | |-ResultSetHandler.java| | |-statement| | | |-BaseStatementHandler.java| | | |-PreparedStatementHandler.java| | | |-SimpleStatementHandler.java| | | |-StatementHandler.java| | |-BaseExecutor.java| | |-Executor.java| | |-SimpleExecutor.java| |-io| | |-Resources.java| |-mapping| | |-BoundSql.java| | |-Environment.java| | |-MappedStatement.java| | |-ParameterMapping.java| | |-SqlCommandType.java| |-reflection| | |-factory| | | |-DefaultObjectFactory.java| | | |-ObjectFactory.java| | |-invoker| | | |-GetFieldInvoker.java| | | |-Invoker.java| | | |-MethodInvoker.java| | | |-SetFieldInvoker.java| | |-property| | | |-PropertyNamer.java| | | |-PropertyTokenizer.java| | |-wrapper| | | |-BaseWrapper.java| | | |-BeanWrapper.java| | | |-CollectionWrapper.java| | | |-DefaultObjectWrapperFactory.java| | | |-MapWrapper.java| | | |-ObjectWrapper.java| | | |-ObjectWrapperFactory.java| | |-MetaClass.java| | |-MetaObject.java| | |-Reflector.java| | |-SystemMetaObject.java| |-session| | |-defaults| | | |-DefaultSqlSession.java| | | |-DefaultSqlSessionFactory.java| | |-Configuration.java| | |-ResultHandler.java| | |-SqlSession.java| | |-SqlSessionFactory.java| | |-SqlSessionFactoryBuilder.java| | |-TransactionIsolationLevel.java| |-transaction| | |-jdbc| | | |-JdbcTransaction.java| | | |-JdbcTransactionFactory.java| | |-Transaction.java| | |-TransactionFactory.java| |-type| | |-JdbcType.java| | |-TypeAliasRegistry.java|-test|-java| |-com.lino.mybatis.test| |-dao| | |-IUserDao.java| |-po| | |-Student.java| | |-Teacher.java| | |-User.java| |-ApiTest.java| |-ReflectionTest.java|-resources|-mapper| |-User_Mapper.xml|-mybatis-config-datasource.xml3.2 元对象反射类关系图 以 Reflector 反射器类处理对象类中的 get/set 属性包装为可调用的 Invoker 反射类。 这样在对 get/set 方法反射调用时使用方法名称获取对应的 invoke 即可 getGetInvoker(String propertyName)。 有了反射器的处理之后就是对原对象的包装由 SystemMetaObject 提供创建 MetaObject 元对象的方法。 将我们需要处理的对象进行拆解和 ObjectWrapper 对象包装处理。因为一个对象的类型还需要进行一条细节的处理以及属性信息的拆解。例如班级[0].学生.成绩 这样的一个类中的关联类的属性则需要进行递归的方式拆解处理后才能设置和获取属性值。 最终在 Mybatis 其他的地方有需要属性值设定时就可以使用反射工具包进行处理了。
3.3 反射调用者
关于对象类中的属性值获取和设置可以分为 Field 字段的 get/set 还有普通的 Method 的调用。为了减少使用方的过多处理这里可以把集中调用者的实现包装成调用策略统一接口不同策略不同的实现类。
3.3.1 统一调用者接口 Invoker.java package com.lino.mybatis.reflection.invoker;/*** description: 调用者*/
public interface Invoker {/*** 调用** param target 目标对象* param args 对象数组* return Object* throws Exception 异常*/Object invoke(Object target, Object[] args) throws Exception;/*** 获取类的类型** return Class?*/Class? getType();
}无论任何类型的反射调用都离不开对象和入参只要我们把这两个字段和返回结果定义的通用就可以包住不同策略的实现类。
3.3.2 方法调用者 MethodInvoker.java package com.lino.mybatis.reflection.invoker;import java.lang.reflect.Method;/*** description: 方法调用者*/
public class MethodInvoker implements Invoker {private Class? type;private Method method;public MethodInvoker(Method method) {this.method method;// 如果只有一个参数返回参数类型否则返回 return 类型if (method.getParameterTypes().length 1) {type method.getParameterTypes()[0];} else {type method.getReturnType();}}Overridepublic Object invoke(Object target, Object[] args) throws Exception {return method.invoke(target, args);}Overridepublic Class? getType() {return type;}
}提供方法反射调用处理构造函数会传入对应的方法类型。
3.3.3 getter 调用者 GetFieldInvoker.java package com.lino.mybatis.reflection.invoker;import java.lang.reflect.Field;/*** description: getter 调用者*/
public class GetFieldInvoker implements Invoker {private Field field;public GetFieldInvoker(Field field) {this.field field;}Overridepublic Object invoke(Object target, Object[] args) throws Exception {return field.get(target);}Overridepublic Class? getType() {return field.getType();}
}getter 方法的调用者处理因为 get 是有返回值的所以直接对 Field 字段操作完后直接返回结果。
3.3.4 setter 调用者 SetFieldInvoker.java package com.lino.mybatis.reflection.invoker;import java.lang.reflect.Field;/*** description: setter 调用者*/
public class SetFieldInvoker implements Invoker {private Field field;public SetFieldInvoker(Field field) {this.field field;}Overridepublic Object invoke(Object target, Object[] args) throws Exception {field.set(target, args);return null;}Overridepublic Class? getType() {return field.getType();}
}setter 方法的调用者处理因为 set 只是设置值所以这里就是返回一个 null 就可以。
3.4 属性命名和分解标记
3.4.1 属性命名器 PropertyNamer.java package com.lino.mybatis.reflection.property;import java.util.Locale;/*** description: 属性命名器*/
public class PropertyNamer {private PropertyNamer() {}/*** 方法转换为属性** param name 方法名称* return String*/public static String methodToProperty(String name) {if (name.startsWith(is)) {name name.substring(2);} else if (name.startsWith(get) || name.startsWith(set)) {name name.substring(3);} else {throw new RuntimeException(Error parsing property name name . Didnt start with is, get, set.);}/*如果只有1个字母转换为小写如果大于1个字母第二个字母非大写转换为小写*/if (name.length() 1 || (name.length() 1 !Character.isUpperCase(name.charAt(1)))) {name name.substring(0, 1).toLowerCase(Locale.ENGLISH) name.substring(1);}return name;}/*** 开头判断get/set/is** param name 名称* return boolean*/public static boolean isProperty(String name) {return name.startsWith(get) || name.startsWith(set) || name.startsWith(is);}/*** 是否为getter** param name 名称* return boolean*/public static boolean isGetter(String name) {return name.startsWith(get) || name.startsWith(is);}/*** 是否为setter** param name 名称* return boolean*/public static boolean isSetter(String name) {return name.startsWith(set);}
}3.4.2 属性分解标记 PropertyTokenizer.java package com.lino.mybatis.reflection.property;import java.util.Iterator;/*** description: 属性分解标记*/
public class PropertyTokenizer implements IterablePropertyTokenizer, IteratorPropertyTokenizer {// 例子班级[0].学生.成绩/*** 属性名称班级*/private String name;/*** 属性对象名称班级[0]*/private String indexedName;/*** 属性索引0*/private String index;/*** 子属性学生*/private String children;public PropertyTokenizer(String fullName) {// 班级[0].学生.成绩找.int delim fullName.indexOf(.);if (delim -1) {name fullName.substring(0, delim);children fullName.substring(delim 1);} else {// 找不到.的话取全部部分name fullName;children null;}indexedName name;// 把中括号里的数字解析出来delim name.indexOf([);if (delim -1) {index name.substring(delim 1, name.length() - 1);name name.substring(0, delim);}}Overridepublic IteratorPropertyTokenizer iterator() {return this;}Overridepublic boolean hasNext() {return children ! null;}Overridepublic PropertyTokenizer next() {return new PropertyTokenizer(children);}public String getName() {return name;}public String getIndexedName() {return indexedName;}public String getIndex() {return index;}public String getChildren() {return children;}
}3.5 反射器解耦对象
Reflector 反射器专门用于解耦对象信息只有把一个对象信息所包含的属性、方法以及关联的类都以此解析出来才能满足后续对属性值的设置和获取。 Reflector.java package com.lino.mybatis.reflection;import com.lino.mybatis.reflection.invoker.GetFieldInvoker;
import com.lino.mybatis.reflection.invoker.Invoker;
import com.lino.mybatis.reflection.invoker.MethodInvoker;
import com.lino.mybatis.reflection.invoker.SetFieldInvoker;
import com.lino.mybatis.reflection.property.PropertyNamer;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;/*** description: 反射器属性 get/set 的映射器*/
public class Reflector {private static boolean classCacheEnabled true;private static final String[] EMPTY_STRING_ARRAY new String[0];/*** 线程安全的缓存*/private static final MapClass?, Reflector REFLECTOR_MAP new ConcurrentHashMap();private Class? type;/*** get 属性列表*/private String[] readablePropertyNames EMPTY_STRING_ARRAY;/*** set 属性列表*/private String[] writeablePropertyNames EMPTY_STRING_ARRAY;/*** set 方法列表*/private MapString, Invoker setMethods new HashMap(16);/*** get 方法列表*/private MapString, Invoker getMethods new HashMap(16);/*** set 类型列表*/private MapString, Class? setTypes new HashMap(16);/*** get 类型列表*/private MapString, Class? getTypes new HashMap(16);/*** 构造函数*/private Constructor? defaultConstructor;private MapString, String caseInsensitivePropertyMap new HashMap(16);public Reflector(Class? clazz) {this.type clazz;// 加入构造函数addDefaultConstructor(clazz);// 加入getteraddGetMethods(clazz);// 加入setteraddSetMethods(clazz);// 加入字段addFields(clazz);readablePropertyNames getMethods.keySet().toArray(new String[0]);writeablePropertyNames setMethods.keySet().toArray(new String[0]);for (String propertyName : readablePropertyNames) {caseInsensitivePropertyMap.put(propertyName.toUpperCase(Locale.ENGLISH), propertyName);}for (String propertyName : writeablePropertyNames) {caseInsensitivePropertyMap.put(propertyName.toUpperCase(Locale.ENGLISH), propertyName);}}/*** 加入构造函数** param clazz 对象类型*/private void addDefaultConstructor(Class? clazz) {Constructor?[] constes clazz.getDeclaredConstructors();for (Constructor? constructor : constes) {if (constructor.getParameterTypes().length 0) {if (canAccessPrivateMethods()) {try {constructor.setAccessible(true);} catch (Exception ignore) {}}if (constructor.isAccessible()) {this.defaultConstructor constructor;}}}}/*** 加入getter方法** param clazz 对象类型*/private void addGetMethods(Class? clazz) {MapString, ListMethod conflictingGetters new HashMap(16);Method[] methods getClassMethods(clazz);for (Method method : methods) {String name method.getName();if (name.startsWith(get) name.length() 3) {if (method.getParameterTypes().length 0) {name PropertyNamer.methodToProperty(name);addMethodConflict(conflictingGetters, name, method);}} else if (name.startsWith(is) name.length() 2) {if (method.getParameterTypes().length 0) {name PropertyNamer.methodToProperty(name);addMethodConflict(conflictingGetters, name, method);}}}resolveGetterConflicts(conflictingGetters);}/*** 加入setter方法** param clazz 对象类型*/private void addSetMethods(Class? clazz) {MapString, ListMethod conflictingSetters new HashMap(16);Method[] methods getClassMethods(clazz);for (Method method : methods) {String name method.getName();if (name.startsWith(set) name.length() 3) {if (method.getParameterTypes().length 1) {name PropertyNamer.methodToProperty(name);addMethodConflict(conflictingSetters, name, method);}}}resolveSetterConflicts(conflictingSetters);}/*** 加入字段** param clazz 对象类型*/private void addFields(Class? clazz) {Field[] fields clazz.getDeclaredFields();for (Field field : fields) {if (canAccessPrivateMethods()) {try {field.setAccessible(true);} catch (Exception e) {}}if (field.isAccessible()) {if (!setMethods.containsKey(field.getName())) {int modifiers field.getModifiers();if (!(Modifier.isFinal(modifiers) Modifier.isStatic(modifiers))) {addSetField(field);}}if (!getMethods.containsKey(field.getName())) {addGetField(field);}}}if (clazz.getSuperclass() ! null) {addFields(clazz.getSuperclass());}}private boolean canAccessPrivateMethods() {try {SecurityManager securityManager System.getSecurityManager();if (null ! securityManager) {securityManager.checkPermission(new ReflectPermission(suppressAccessChecks));}} catch (SecurityException e) {return false;}return true;}private void resolveGetterConflicts(MapString, ListMethod conflictingGetters) {for (String propName : conflictingGetters.keySet()) {ListMethod getters conflictingGetters.get(propName);IteratorMethod iterator getters.iterator();Method firstMethod iterator.next();if (getters.size() 1) {addGetMethod(propName, firstMethod);} else {Method getter firstMethod;Class? getterType firstMethod.getReturnType();while (iterator.hasNext()) {Method method iterator.next();Class? methodType method.getReturnType();if (methodType.equals(getterType)) {throw new RuntimeException(Illegal overloaded getter method with ambiguous type for property propName in class firstMethod.getDeclaringClass() . This breaks the JavaBeans specification and can cause unpredicatble results.);} else if (methodType.isAssignableFrom(getterType)) {// OK getter type is descendant} else if (getterType.isAssignableFrom(methodType)) {getter method;getterType methodType;} else {throw new RuntimeException(Illegal overloaded getter method with ambiguous type for property propName in class firstMethod.getDeclaringClass() . This breaks the JavaBeans specification and can cause unpredicatble results.);}}addGetMethod(propName, getter);}}}private void resolveSetterConflicts(MapString, ListMethod conflictingSetters) {for (String propName : conflictingSetters.keySet()) {ListMethod setters conflictingSetters.get(propName);Method firstMethod setters.get(0);if (setters.size() 1) {addSetMethod(propName, firstMethod);} else {Class? expectedType getTypes.get(propName);if (expectedType null) {throw new RuntimeException(Illegal overloaded setter method with ambiguous type for property propName in class firstMethod.getDeclaringClass() . This breaks the JavaBeans specification and can cause unpredicatble results.);} else {IteratorMethod methods setters.iterator();Method setter null;while (methods.hasNext()) {Method method methods.next();if (method.getParameterTypes().length 1 expectedType.equals(method.getParameterTypes()[0])) {setter method;break;}}if (setter null) {throw new RuntimeException(Illegal overloaded setter method with ambiguous type for property propName in class firstMethod.getDeclaringClass() . This breaks the JavaBeans specification and can cause unpredicatble results.);}addSetMethod(propName, setter);}}}}private boolean isValidPropertyName(String name) {return !(name.startsWith($) || serialVersionUID.equals(name) || class.equals(name));}private void addSetMethod(String name, Method method) {if (isValidPropertyName(name)) {setMethods.put(name, new MethodInvoker(method));setTypes.put(name, method.getParameterTypes()[0]);}}private void addGetMethod(String name, Method method) {if (isValidPropertyName(name)) {getMethods.put(name, new MethodInvoker(method));getTypes.put(name, method.getReturnType());}}private void addSetField(Field field) {if (isValidPropertyName(field.getName())) {setMethods.put(field.getName(), new SetFieldInvoker(field));setTypes.put(field.getName(), field.getType());}}private void addGetField(Field field) {if (isValidPropertyName(field.getName())) {getMethods.put(field.getName(), new GetFieldInvoker(field));getTypes.put(field.getName(), field.getType());}}private Method[] getClassMethods(Class? clazz) {MapString, Method uniqueMethods new HashMap(16);Class? currentClass clazz;while (currentClass ! null) {addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());// 循环判断类是否是抽象类Class?[] interfaces currentClass.getInterfaces();for (Class? anInterface : interfaces) {addUniqueMethods(uniqueMethods, anInterface.getDeclaredMethods());}currentClass currentClass.getSuperclass();}CollectionMethod methods uniqueMethods.values();return methods.toArray(new Method[0]);}private void addUniqueMethods(MapString, Method uniqueMethods, Method[] methods) {for (Method currentMethod : methods) {if (!currentMethod.isBridge()) {// 取得签名String signature getSignature(currentMethod);// check to see if the method is already known// if it is known, then an extended class must have// overridden a methodif (!uniqueMethods.containsKey(signature)) {if (canAccessPrivateMethods()) {try {currentMethod.setAccessible(true);} catch (Exception e) {}}uniqueMethods.put(signature, currentMethod);}}}}private String getSignature(Method method) {StringBuilder sb new StringBuilder();Class? returnType method.getReturnType();if (returnType ! null) {sb.append(returnType.getName()).append(#);}sb.append(method.getName());Class?[] parameters method.getParameterTypes();for (int i 0; i parameters.length; i) {if (i 0) {sb.append(:);} else {sb.append(,);}sb.append(parameters[i].getName());}return sb.toString();}private void addMethodConflict(MapString, ListMethod conflictingGetters, String name, Method method) {ListMethod list conflictingGetters.computeIfAbsent(name, k - new ArrayList());list.add(method);}public Class? getType() {return type;}public Constructor? getDefaultConstructor() {if (defaultConstructor ! null) {return defaultConstructor;} else {throw new RuntimeException(There is no default constructor for type);}}public boolean hasDefaultConstructor() {return defaultConstructor ! null;}public Invoker getGetInvoker(String propertyName) {Invoker method getMethods.get(propertyName);if (method null) {throw new RuntimeException(There is no getter for property named propertyName in type );}return method;}public Invoker getSetInvoker(String propertyName) {Invoker method setMethods.get(propertyName);if (method null) {throw new RuntimeException(There is no setter for property named propertyName in type );}return method;}public Class? getSetterType(String propertyName) {Class? clazz setTypes.get(propertyName);if (clazz null) {throw new RuntimeException(There is no setter for property named propertyName in type );}return clazz;}public Class? getGetterType(String propertyName) {Class? clazz getTypes.get(propertyName);if (clazz null) {throw new RuntimeException(There is no getter for property named propertyName in type );}return clazz;}public String[] getGetablePropertyNames() {return readablePropertyNames;}public String[] getSetablePropertyNames() {return writeablePropertyNames;}public boolean hasSetter(String propertyName) {return setMethods.keySet().contains(propertyName);}public boolean hasGetter(String propertyName) {return getMethods.keySet().contains(propertyName);}public String findPropertyName(String name) {return caseInsensitivePropertyMap.get(name.toUpperCase(Locale.ENGLISH));}public static Reflector forClass(Class? clazz) {if (classCacheEnabled) {// 对于每个类来说我们假设它是不会变的这样可以考虑将这个类的信息(构造函数gettersetter字段)加入缓存以提高速度Reflector cached REFLECTOR_MAP.get(clazz);if (cached null) {cached new Reflector(clazz);REFLECTOR_MAP.put(clazz, cached);}return cached;} else {return new Reflector(clazz);}}public static boolean isClassCacheEnabled() {return classCacheEnabled;}public static void setClassCacheEnabled(boolean classCacheEnabled) {Reflector.classCacheEnabled classCacheEnabled;}
}Reflector 反射器类中提供了各类属性、方法、类型以及构造函数的保存操作。当调用反射器时会通过构造函数的处理逐步从对象类中拆解出这些属性信息便于后续反射使用。
3.6 元类包装反射器
Reflector 反射器类提供的是最基础的核心功能很多方法都是私有的为了更方便使用还需要做一层元类的包装。在元类 MetaClass 提供必要的创建反射器以及使用反射器获取 get/set 的 Invoker 反射方法。 MetaClass.java package com.lino.mybatis.reflection;import com.lino.mybatis.reflection.invoker.GetFieldInvoker;
import com.lino.mybatis.reflection.invoker.Invoker;
import com.lino.mybatis.reflection.invoker.MethodInvoker;
import com.lino.mybatis.reflection.property.PropertyTokenizer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;/*** description: 元类*/
public class MetaClass {private Reflector reflector;public MetaClass(Class? type) {this.reflector Reflector.forClass(type);}public static MetaClass forClass(Class? type) {return new MetaClass(type);}public static boolean isClassCacheEnabled() {return Reflector.isClassCacheEnabled();}public static void setClassCacheEnabled(boolean classCacheEnabled) {Reflector.setClassCacheEnabled(classCacheEnabled);}public MetaClass metaClassForProperty(String name) {Class? propType reflector.getGetterType(name);return MetaClass.forClass(propType);}public MetaClass metaClassForProperty(PropertyTokenizer prop) {Class? propType getGetterType(prop);return MetaClass.forClass(propType);}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 metaProp metaClassForProperty(propertyName);metaProp.buildProperty(prop.getChildren(), builder);}} else {String propertyName reflector.findPropertyName(name);if (propertyName ! null) {builder.append(propertyName);}}return builder;}public String findProperty(String name) {StringBuilder prop buildProperty(name, new StringBuilder());return prop.length() 0 ? prop.toString() : null;}public String findProperty(String name, boolean useCameCaseMapping) {if (useCameCaseMapping) {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());}// 解析集合对象中的类型return getGetterType(prop);}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 method.getGenericReturnType();} else if (invoker instanceof GetFieldInvoker) {Field _field GetFieldInvoker.class.getDeclaredField(field);_field.setAccessible(true);Field field (Field) _field.get(invoker);return field.getGenericType();}} 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);}public boolean hasDefaultConstructor() {return reflector.hasDefaultConstructor();}
}MetaClass 元类相当于是对我们需要处理对象的包装解耦一个原对象包装出一个元类、对象包装器以及对象工厂等再组合出一个元对象。相当于说这些元类和元对象都是对我们需要操作的原对象解耦后的封装。有了这样的操作就可以让我们处理每一个属性或者方法。
3.7 对象包装器 Wrapper
对象包装器相当于是更加进一步反射调用包装处理同时也为不同的对象类型提供不同的包装策略。再对象包装器接口中定义了更加明确的需要使用的方法包括定义出 get/set 标准的通用方法、获取 get/set 属性名称和属性类型以及添加属性等。
3.7.1 对象包装器接口 ObjectWrapper.java package com.lino.mybatis.reflection.wrapper;import com.lino.mybatis.reflection.MetaObject;
import com.lino.mybatis.reflection.factory.ObjectFactory;
import com.lino.mybatis.reflection.property.PropertyTokenizer;
import java.util.List;/*** description: 对象包装器*/
public interface ObjectWrapper {/*** get获取** param prop 属性分解标记* return Object*/Object get(PropertyTokenizer prop);/*** set设置** param prop 属性分解标记* param value 值*/void set(PropertyTokenizer prop, Object value);/*** 查找属性** param name 属性名称* param useCameCaseMapping 是否使用强制映射* return 属性*/String findProperty(String name, boolean useCameCaseMapping);/*** 取得getter的名字列表** return getter的名字列表*/String[] getGetterNames();/*** 取得setter的名字列表** return setter的名字列表*/String[] getSetterNames();/*** 取得setter的类型** param name 属性名称* return setter的类型*/Class? getSetterType(String name);/*** 取得getter的类型** param name 属性名称* return getter的类型*/Class? getGetterType(String name);/*** 是否有指定的setter** param name 属性名* return 是否有指定的setter*/boolean hasSetter(String name);/*** 是否有指定的getter** param name 属性名* return 是否有指定的getter*/boolean hasGetter(String name);/*** 实例化属性** param name 属性名* param prop 属性分解标记* param objectFactory 对象工厂接口* return 元对象*/MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory);/*** 是否是集合** return boolean*/boolean isCollection();/*** 添加属性** param element 属性对象*/void add(Object element);/*** 添加属性集合** param elements 属性对象集合* param E 属性泛型*/E void addAll(ListE elements);
}后续所有实现了对象包装器接口的实现类都需要提供这些方法实现基本有了这些方法也就能非常容易的处理一个对象的反射操作。方法设置属性、获取属性、获取字段列表获取字段类型
3.7.2 对象包装器抽象基类 BaseWrapper.java package com.lino.mybatis.reflection.wrapper;import com.lino.mybatis.reflection.MetaObject;
import com.lino.mybatis.reflection.property.PropertyTokenizer;import java.util.List;
import java.util.Map;/*** description: 对象包装器抽象基类提供一些工具方法* author: lingjian* createDate: 2022/11/9 9:55*/
public abstract class BaseWrapper implements ObjectWrapper {protected static final Object[] NO_ARGUMENTS new Object[0];protected MetaObject metaObject;public BaseWrapper(MetaObject metaObject) {this.metaObject metaObject;}/*** 解析集合** param prop 属性分解标记* param object 对象* return Object 对象*/protected Object resolveCollection(PropertyTokenizer prop, Object object) {if (.equals(prop.getName())) {return object;} else {return metaObject.getValue(prop.getName());}}/*** 取集合的值** param prop 属性分解标记* param collection 对象{MapList/Array}* return Object 属性对象*/protected Object getCollectionValue(PropertyTokenizer prop, Object collection) {if (collection instanceof Map) {// map[name]return ((Map) collection).get(prop.getIndex());} else {int i Integer.parseInt(prop.getIndex());if (collection instanceof List) {// list[0]return ((List) collection).get(i);} else if (collection instanceof Object[]) {return ((Object[]) collection)[i];} else if (collection instanceof char[]) {return ((char[]) collection)[i];} else if (collection instanceof boolean[]) {return ((boolean[]) collection)[i];} else if (collection instanceof byte[]) {return ((byte[]) collection)[i];} else if (collection instanceof double[]) {return ((double[]) collection)[i];} else if (collection instanceof float[]) {return ((float[]) collection)[i];} else if (collection instanceof int[]) {return ((int[]) collection)[i];} else if (collection instanceof long[]) {return ((long[]) collection)[i];} else if (collection instanceof short[]) {return ((short[]) collection)[i];} else {throw new RuntimeException(The prop.getName() property of collection is not a List or Array.);}}}/*** 设置集合的值** param prop 属性分解标记* param collection 对象{MapList/Array}* param value 值*/protected void setCollectionValue(PropertyTokenizer prop, Object collection, Object value) {if (collection instanceof Map) {// map[name]((Map) collection).put(prop.getIndex(), value);} else {int i Integer.parseInt(prop.getIndex());if (collection instanceof List) {((List) collection).set(i, value);} else if (collection instanceof Object[]) {((Object[]) collection)[i] value;} else if (collection instanceof char[]) {((char[]) collection)[i] (Character) value;} else if (collection instanceof boolean[]) {((boolean[]) collection)[i] (Boolean) value;} else if (collection instanceof byte[]) {((byte[]) collection)[i] (Byte) value;} else if (collection instanceof double[]) {((double[]) collection)[i] (Double) value;} else if (collection instanceof float[]) {((float[]) collection)[i] (Float) value;} else if (collection instanceof int[]) {((int[]) collection)[i] (Integer) value;} else if (collection instanceof long[]) {((long[]) collection)[i] (Long) value;} else if (collection instanceof short[]) {((short[]) collection)[i] (Short) value;} else {throw new RuntimeException(The prop.getName() property of collection is not a List or Array.);}}}
}3.7.3 Bean 包装器 BeanWrapper.java package com.lino.mybatis.reflection.wrapper;import com.lino.mybatis.reflection.MetaClass;
import com.lino.mybatis.reflection.MetaObject;
import com.lino.mybatis.reflection.SystemMetaObject;
import com.lino.mybatis.reflection.factory.ObjectFactory;
import com.lino.mybatis.reflection.invoker.Invoker;
import com.lino.mybatis.reflection.property.PropertyTokenizer;
import java.util.List;/*** description: Bean 包装器*/
public class BeanWrapper extends BaseWrapper {/*** 原来的对象*/private Object object;/*** 元类*/private MetaClass metaClass;public BeanWrapper(MetaObject metaObject, Object object) {super(metaObject);this.object object;this.metaClass MetaClass.forClass(object.getClass());}Overridepublic Object get(PropertyTokenizer prop) {// 如果有index(有中括号)说明是集合那就要解析集合调用的是 BaseWrapper.resolveCollection 和 getCollectionValueif (prop.getIndex() ! null) {Object collection resolveCollection(prop, object);return getCollectionValue(prop, collection);} else {// 否则 getBeanPropertyreturn getBeanProperty(prop, object);}}private Object getBeanProperty(PropertyTokenizer prop, Object object) {try {// 得到getter方法然后调用Invoker method metaClass.getGetInvoker(prop.getName());return method.invoke(object, NO_ARGUMENTS);} catch (RuntimeException e) {throw e;} catch (Throwable t) {throw new RuntimeException(Count not get property prop.getName() from object.getClass() . Cause: t, t);}}Overridepublic void set(PropertyTokenizer prop, Object value) {// 如果有index(有中括号)说明是集合那就要解析集合调用的是 BaseWrapper.resolveCollection 和 getCollectionValueif (prop.getIndex() ! null) {Object collection resolveCollection(prop, object);setCollectionValue(prop, collection, value);} else {// 否则 setBeanPropertysetBeanProperty(prop, object, value);}}private void setBeanProperty(PropertyTokenizer prop, Object object, Object value) {try {// 得到getter方法然后调用Invoker method metaClass.getSetInvoker(prop.getName());Object[] params {value};method.invoke(object, params);} catch (Throwable t) {throw new RuntimeException(Count not set property prop.getName() of object.getClass() with value value Cause: t, t);}}Overridepublic String findProperty(String name, boolean useCameCaseMapping) {return metaClass.findProperty(name, useCameCaseMapping);}Overridepublic String[] getGetterNames() {return metaClass.getGetterNames();}Overridepublic String[] getSetterNames() {return metaClass.getSetterNames();}Overridepublic Class? getSetterType(String name) {PropertyTokenizer prop new PropertyTokenizer(name);if (prop.hasNext()) {MetaObject metaValue metaObject.metaObjectForProperty(prop.getIndexedName());if (metaValue SystemMetaObject.NULL_META_OBJECT) {return metaClass.getSetterType(name);} else {return metaValue.getSetterType(prop.getChildren());}} else {return metaClass.getSetterType(name);}}Overridepublic Class? getGetterType(String name) {PropertyTokenizer prop new PropertyTokenizer(name);if (prop.hasNext()) {MetaObject metaValue metaObject.metaObjectForProperty(prop.getIndexedName());if (metaValue SystemMetaObject.NULL_META_OBJECT) {return metaClass.getGetterType(name);} else {return metaValue.getGetterType(prop.getChildren());}} else {return metaClass.getGetterType(name);}}Overridepublic boolean hasSetter(String name) {PropertyTokenizer prop new PropertyTokenizer(name);if (prop.hasNext()) {if (metaObject.hasSetter(prop.getIndexedName())) {MetaObject metaValue metaObject.metaObjectForProperty(prop.getIndexedName());if (metaValue SystemMetaObject.NULL_META_OBJECT) {return metaClass.hasSetter(name);} else {return metaValue.hasSetter(prop.getChildren());}} else {return false;}} else {return metaClass.hasSetter(name);}}Overridepublic boolean hasGetter(String name) {PropertyTokenizer prop new PropertyTokenizer(name);if (prop.hasNext()) {if (metaObject.hasGetter(prop.getIndexedName())) {MetaObject metaValue metaObject.metaObjectForProperty(prop.getIndexedName());if (metaValue SystemMetaObject.NULL_META_OBJECT) {return metaClass.hasGetter(name);} else {return metaValue.hasGetter(prop.getChildren());}} else {return false;}} else {return metaClass.hasGetter(name);}}Overridepublic MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {MetaObject metaValue;Class? type getSetterType(prop.getName());try {Object newObject objectFactory.create(type);metaValue MetaObject.forObject(newObject, metaObject.getObjectFactory(), metaObject.getObjectWrapperFactory());set(prop, newObject);} catch (Exception e) {throw new RuntimeException(Cannot set value of property name because name is null and cannot be instantiated on instance of type.getName() . Cause: e, e);}return metaValue;}Overridepublic boolean isCollection() {return false;}Overridepublic void add(Object element) {throw new UnsupportedOperationException();}Overridepublic E void addAll(ListE elements) {throw new UnsupportedOperationException();}
}3.7.4 Collection 包装器 CollectionWrapper.java package com.lino.mybatis.reflection.wrapper;import com.lino.mybatis.reflection.MetaObject;
import com.lino.mybatis.reflection.factory.ObjectFactory;
import com.lino.mybatis.reflection.property.PropertyTokenizer;
import java.util.Collection;
import java.util.List;/*** description: Collection 包装器*/
public class CollectionWrapper implements ObjectWrapper {/*** 原始对象*/private CollectionObject object;public CollectionWrapper(MetaObject metaObject, CollectionObject object) {this.object object;}Overridepublic Object get(PropertyTokenizer prop) {throw new UnsupportedOperationException();}Overridepublic void set(PropertyTokenizer prop, Object value) {throw new UnsupportedOperationException();}Overridepublic String findProperty(String name, boolean useCameCaseMapping) {throw new UnsupportedOperationException();}Overridepublic String[] getGetterNames() {throw new UnsupportedOperationException();}Overridepublic String[] getSetterNames() {throw new UnsupportedOperationException();}Overridepublic Class? getSetterType(String name) {throw new UnsupportedOperationException();}Overridepublic Class? getGetterType(String name) {throw new UnsupportedOperationException();}Overridepublic boolean hasSetter(String name) {throw new UnsupportedOperationException();}Overridepublic boolean hasGetter(String name) {throw new UnsupportedOperationException();}Overridepublic MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {throw new UnsupportedOperationException();}Overridepublic boolean isCollection() {return true;}Overridepublic void add(Object element) {object.add(element);}Overridepublic E void addAll(ListE elements) {object.addAll(elements);}
}3.7.5 MapWrapper 包装器 MapWrapper.java package com.lino.mybatis.reflection.wrapper;import com.lino.mybatis.reflection.MetaObject;
import com.lino.mybatis.reflection.SystemMetaObject;
import com.lino.mybatis.reflection.factory.ObjectFactory;
import com.lino.mybatis.reflection.property.PropertyTokenizer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** description: Map 包装器*/
public class MapWrapper extends BaseWrapper {/*** 原始对象*/private MapString, Object map;public MapWrapper(MetaObject metaObject, MapString, Object map) {super(metaObject);this.map map;}Overridepublic Object get(PropertyTokenizer prop) {// 如果有index(有中括号)说明是集合那就要解析集合调用的是 BaseWrapper.resolveCollection 和 getCollectionValueif (prop.getIndex() ! null) {Object collection resolveCollection(prop, map);return getCollectionValue(prop, collection);} else {return map.get(prop.getName());}}Overridepublic void set(PropertyTokenizer prop, Object value) {// 如果有index(有中括号)说明是集合那就要解析集合调用的是 BaseWrapper.resolveCollection 和 getCollectionValueif (prop.getIndex() ! null) {Object collection resolveCollection(prop, map);setCollectionValue(prop, collection, value);} else {// 否则 setBeanPropertymap.put(prop.getName(), value);}}Overridepublic String findProperty(String name, boolean useCameCaseMapping) {return name;}Overridepublic String[] getGetterNames() {return map.keySet().toArray(new String[0]);}Overridepublic String[] getSetterNames() {return map.keySet().toArray(new String[0]);}Overridepublic Class? getSetterType(String name) {PropertyTokenizer prop new PropertyTokenizer(name);if (prop.hasNext()) {MetaObject metaValue metaObject.metaObjectForProperty(prop.getIndexedName());if (metaValue SystemMetaObject.NULL_META_OBJECT) {return Object.class;} else {return metaValue.getSetterType(prop.getChildren());}} else {if (map.get(name) ! null) {return map.get(name).getClass();} else {return Object.class;}}}Overridepublic Class? getGetterType(String name) {PropertyTokenizer prop new PropertyTokenizer(name);if (prop.hasNext()) {MetaObject metaValue metaObject.metaObjectForProperty(prop.getIndexedName());if (metaValue SystemMetaObject.NULL_META_OBJECT) {return Object.class;} else {return metaValue.getGetterType(prop.getChildren());}} else {if (map.get(name) ! null) {return map.get(name).getClass();} else {return Object.class;}}}Overridepublic boolean hasSetter(String name) {return true;}Overridepublic boolean hasGetter(String name) {PropertyTokenizer prop new PropertyTokenizer(name);if (prop.hasNext()) {if (map.containsKey(prop.getIndexedName())) {MetaObject metaValue metaObject.metaObjectForProperty(prop.getIndexedName());if (metaValue SystemMetaObject.NULL_META_OBJECT) {return true;} else {return metaValue.hasGetter(prop.getChildren());}} else {return false;}} else {return map.containsKey(prop.getName());}}Overridepublic MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {HashMapString, Object map new HashMap(16);set(prop, map);return MetaObject.forObject(map, metaObject.getObjectFactory(), metaObject.getObjectWrapperFactory());}Overridepublic boolean isCollection() {return false;}Overridepublic void add(Object element) {throw new UnsupportedOperationException();}Overridepublic E void addAll(ListE elements) {throw new UnsupportedOperationException();}
}3.8 对象包装工厂
通过包装工厂获取包装器
3.8.1 对象包装工厂接口 ObjectWrapperFactory.java package com.lino.mybatis.reflection.wrapper;import com.lino.mybatis.reflection.MetaObject;/*** description: 对象包装工厂*/
public interface ObjectWrapperFactory {/*** 判断有没有包装器** param object 对象* return boolean*/boolean hasWrapperFor(Object object);/*** 获取包装器** param metaObject 元对象* param object 对象* return 包装器*/ObjectWrapper getWrapperFor(MetaObject metaObject, Object object);
}3.8.2 默认对象包装工厂实现类 DefaultObjectWrapperFactory.java package com.lino.mybatis.reflection.wrapper;import com.lino.mybatis.reflection.MetaObject;/*** description: 默认对象包装器*/
public class DefaultObjectWrapperFactory implements ObjectWrapperFactory {Overridepublic boolean hasWrapperFor(Object object) {return false;}Overridepublic ObjectWrapper getWrapperFor(MetaObject metaObject, Object object) {throw new RuntimeException(The DefaultObjectWrapperFactory should never be called to provide an ObjectWrapper.);}
}3.9 对象工厂
3.9.1 对象工厂接口 ObjectFactory.java package com.lino.mybatis.reflection.factory;import java.util.List;
import java.util.Properties;/*** description: 对象工厂接口*/
public interface ObjectFactory {/*** 设置属性** param properties 属性配置*/void setProperties(Properties properties);/*** 生产对象** param type 对象类型* param T 泛型* return T 泛型对象*/T T create(ClassT type);/*** 生产对象使用指定的构造函数和构造函数参数** param type 对象类型* param constructorArgTypes 构造函数* param constructorArgs 构造函数参数* param T 泛型* return T 泛型对象*/T T create(ClassT type, ListClass? constructorArgTypes, ListObject constructorArgs);/*** 返回这个对象是否是集合** param type 对象类型* param T 泛型* return 是否是集合*/T boolean isCollection(ClassT type);
}3.9.2 默认对象工厂实现类 DefaultObjectFactory.java package com.lino.mybatis.reflection.factory;import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.*;/*** description: 默认对象工厂所有的对象都由工厂来生成*/
public class DefaultObjectFactory implements ObjectFactory, Serializable {private static final long serialVersionUID -8855120656740914948L;Overridepublic void setProperties(Properties properties) {}Overridepublic T T create(ClassT type) {return create(type, null, null);}SuppressWarnings(unchecked)Overridepublic T T create(ClassT type, ListClass? constructorArgTypes, ListObject constructorArgs) {// 1.解析接口Class? classToCreate resolveInterface(type);// 2.类实例化return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);}private T T instantiateClass(ClassT type, ListClass? constructorArgTypes, ListObject constructorArgs) {try {ConstructorT constructor;// 如果没有传入constructor调用空构造函数核心是调用 Constructor.newInstanceif (constructorArgTypes null || constructorArgs null) {constructor type.getDeclaredConstructor();if (!constructor.isAccessible()) {constructor.setAccessible(true);}return constructor.newInstance();}// 如果传入constructor调用传入的构造函数核心是调用 Constructor.newInstanceconstructor type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[0]));if (!constructor.isAccessible()) {constructor.setAccessible(true);}return constructor.newInstance(constructorArgs.toArray(new Object[0]));} catch (Exception e) {// 如果出错包装一下重新抛出自己的异常StringBuilder argTypes new StringBuilder();if (constructorArgTypes ! null) {for (Class? argType : constructorArgTypes) {argTypes.append(argType.getSimpleName());argTypes.append(,);}}StringBuilder argValues new StringBuilder();if (constructorArgs ! null) {for (Object argType : constructorArgs) {argValues.append(argType);argTypes.append(,);}}throw new RuntimeException(Error instantiating type with invalid types ( argTypes ) or values ( argValues ). Cause: e, e);}}/*** 解析接口将 interface 转换为实际的 class类** param type 对象类型* return Class? 实现类*/private Class? resolveInterface(Class? type) {Class? classToCreate;if (type List.class || type Collection.class || type Iterable.class) {// List/Collection/Iterable --- ArrayListclassToCreate ArrayList.class;} else if (type Map.class) {// Map --- HashMapclassToCreate HashMap.class;} else if (type SortedSet.class) {// SortedSet --- TreeSetclassToCreate TreeSet.class;} else if (type Set.class) {// Set --- HashSetclassToCreate HashSet.class;} else {// 除此之外就用原来的原型classToCreate type;}return classToCreate;}Overridepublic T boolean isCollection(ClassT type) {return Collection.class.isAssignableFrom(type);}
}3.10 元对象封装
在有了反射器、元类、对象包装器以后再使用对象工厂和对象包装工厂就可以组合出一个完整的元对象操作类。对元对象的管理包括包装器策略、包装工程、统一的方法处理。
3.10.1 元对象 MetaObject.java package com.lino.mybatis.reflection;import com.lino.mybatis.reflection.factory.ObjectFactory;
import com.lino.mybatis.reflection.property.PropertyTokenizer;
import com.lino.mybatis.reflection.wrapper.*;
import java.util.Collection;
import java.util.List;
import java.util.Map;/*** description: 元对象*/
public class MetaObject {/*** 原始对象*/private Object originalObject;/*** 对象包装器*/private ObjectWrapper objectWrapper;/*** 对象工厂*/private ObjectFactory objectFactory;/*** 对象包装工厂*/private ObjectWrapperFactory objectWrapperFactory;public MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory) {this.originalObject object;this.objectFactory objectFactory;this.objectWrapperFactory objectWrapperFactory;if (object instanceof ObjectWrapper) {// 如果对象本身已经是ObjectWrapper类型则直接赋给objectWrapperthis.objectWrapper (ObjectWrapper) object;} else if (objectWrapperFactory.hasWrapperFor(object)) {// 如果有包装器调用objectWrapperFactory.getWrapperForthis.objectWrapper objectWrapperFactory.getWrapperFor(this, object);} else if (object instanceof Map) {// 如果是Map类型返回MapWrapperthis.objectWrapper new MapWrapper(this, (Map) object);} else if (object instanceof Collection) {// 如果是Collection类型返回CollectionWrapperthis.objectWrapper new CollectionWrapper(this, (Collection) object);} else {// 除此之外返回 BeanWrapperthis.objectWrapper new BeanWrapper(this, object);}}/*** 返回元对象** param object 原始对象* param objectFactory 对象工厂* param objectWrapperFactory 对象包装工厂* return MetaObject 元对象*/public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory) {if (object null) {// 处理一下null将null包装起来return SystemMetaObject.NULL_META_OBJECT;} else {return new MetaObject(object, objectFactory, objectWrapperFactory);}}public Object getOriginalObject() {return originalObject;}public ObjectWrapper getObjectWrapper() {return objectWrapper;}public ObjectFactory getObjectFactory() {return objectFactory;}public ObjectWrapperFactory getObjectWrapperFactory() {return objectWrapperFactory;}/* 以下属性委派给 ObjectWrapper *//*** 查找属性*/public String findProperty(String propName, boolean useCameCaseNapping) {return objectWrapper.findProperty(propName, useCameCaseNapping);}/*** 取得getter的名字列表*/public String[] getGetterNames() {return objectWrapper.getGetterNames();}/*** 取得setter的名字列表*/public String[] getSetterNames() {return objectWrapper.getSetterNames();}/*** 取得setter的类型*/public Class? getSetterType(String children) {return objectWrapper.getSetterType(children);}/*** 取得getter的类型*/public Class? getGetterType(String children) {return objectWrapper.getGetterType(children);}/*** 是否有指定的setter*/public boolean hasSetter(String indexedName) {return objectWrapper.hasSetter(indexedName);}/*** 是否有指定的getter*/public boolean hasGetter(String children) {return objectWrapper.hasGetter(children);}/*** 是否是集合*/public boolean isCollection() {return objectWrapper.isCollection();}/*** 添加属性*/public void add(Object element) {objectWrapper.add(element);}/*** 添加属性集合*/public E void addAll(ListE elements) {objectWrapper.addAll(elements);}/*** 获取值** param name 属性名称* return 值*/public Object getValue(String name) {PropertyTokenizer prop new PropertyTokenizer(name);if (prop.hasNext()) {MetaObject metaValue metaObjectForProperty(prop.getIndexedName());if (metaValue SystemMetaObject.NULL_META_OBJECT) {// 如果上层是null那就结束返回nullreturn null;} else {// 否则继续看下一层递归调用getValuereturn metaValue.getValue(prop.getChildren());}} else {return objectWrapper.get(prop);}}/*** 设置值** param name 属性名* param value 属性值*/public void setValue(String name, Object value) {PropertyTokenizer prop new PropertyTokenizer(name);if (prop.hasNext()) {MetaObject metaValue metaObjectForProperty(prop.getIndexedName());if (metaValue SystemMetaObject.NULL_META_OBJECT) {if (value null prop.getChildren() ! null) {// 如果上层是null还得看有没有子对象没有就结束return;} else {// 否则还得 new 一个委派给 objectWrapper.instantiatePropertyValuemetaValue objectWrapper.instantiatePropertyValue(name, prop, objectFactory);}}// 递归调用setValuemetaValue.setValue(prop.getChildren(), value);} else {// 到最后层了所以委派给 objectWrapper.setobjectWrapper.set(prop, value);}}/*** 为属性生成元对象** param name 属性名* return 元对象*/public MetaObject metaObjectForProperty(String name) {// 递归调用Object value getValue(name);return MetaObject.forObject(value, objectFactory, objectWrapperFactory);}}MetaObject 元对象算是整个服务的包装在构造函数中提供各类对象的包装器类型的创建。 包括这里提供的 getValue(String name)、setValue(String name, Object value) 等。其中当一些对象中的属性信息不是一个层次班级[0].学生.成绩 需要被拆解后才能获取到对应的对象和属性值。
3.10.2 系统级别元对象 SystemMetaObject.java package com.lino.mybatis.reflection;import com.lino.mybatis.reflection.factory.DefaultObjectFactory;
import com.lino.mybatis.reflection.factory.ObjectFactory;
import com.lino.mybatis.reflection.wrapper.DefaultObjectWrapperFactory;
import com.lino.mybatis.reflection.wrapper.ObjectWrapperFactory;/*** description: 系统级别元对象*/
public class SystemMetaObject {public static final ObjectFactory DEFAULT_OBJECT_FACTORY new DefaultObjectFactory();public static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY new DefaultObjectWrapperFactory();public static final MetaObject NULL_META_OBJECT MetaObject.forObject(NullObject.class, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);private SystemMetaObject() {}private static class NullObject {}public static MetaObject forObject(Object object) {return MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);}
}使用 SystemMetaObject#forObject 提供元对象的获取。
3.11 数据源属性设置
现在有了我们实现的属性反射操作工具包那么对于数据源中属性信息的设置就可以使用反射来设置和获取。
3.11.1 无池化数据源工厂 UnpooledDataSourceFactory.java package com.lino.mybatis.datasource.unpooled;import com.lino.mybatis.datasource.DataSourceFactory;
import com.lino.mybatis.reflection.MetaObject;
import com.lino.mybatis.reflection.SystemMetaObject;
import javax.sql.DataSource;
import java.util.Properties;/*** description: 无池化数据源工厂*/
public class UnpooledDataSourceFactory implements DataSourceFactory {protected DataSource dataSource;public UnpooledDataSourceFactory() {this.dataSource new UnpooledDataSource();}Overridepublic void setProperties(Properties props) {MetaObject metaObject SystemMetaObject.forObject(dataSource);for (Object key : props.keySet()) {String propertyName (String) key;if (metaObject.hasSetter(propertyName)) {String value (String) props.get(propertyName);Object convertedValue convertValue(metaObject, propertyName, value);metaObject.setValue(propertyName, convertedValue);}}}Overridepublic DataSource getDataSource() {return dataSource;}/*** 根据setter的类型将配置文件中的值强转成相应的类型** param metaObject 元对象* param propertyName 属性名* param value 属性值* return Object 转化后的对象*/private Object convertValue(MetaObject metaObject, String propertyName, String value) {Object convertedValue value;Class? targetType metaObject.getSetterType(propertyName);if (targetType Integer.class || targetType int.class) {convertedValue Integer.valueOf(value);} else if (targetType Long.class || targetType long.class) {convertedValue Long.valueOf(value);} else if (targetType Boolean.class || targetType boolean.class) {convertedValue Boolean.valueOf(value);}return convertedValue;}
}在 setProperties 方法中使用 SystemMetaObject.forObject(dataSource) 获取 DataSource 的元对象也就是通过反射设置属性值。
3.11.2 有池化数据源工厂 PooledDataSourceFactory.java package com.lino.mybatis.datasource.pooled;import com.lino.mybatis.datasource.unpooled.UnpooledDataSourceFactory;
import javax.sql.DataSource;/*** description: 有连接池的数据源工厂*/
public class PooledDataSourceFactory extends UnpooledDataSourceFactory {public PooledDataSourceFactory() {this.dataSource new PooledDataSource();}
}设置属性继承无池化数据源工厂的属性设置。
四、测试元对象反射类
4.1 单元测试 ApiTest.java Test
public void test_SqlSessionFactoryExecutor() throws IOException {// 1.从SqlSessionFactory中获取SqlSessionSqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader(mybatis-config-datasource.xml));SqlSession sqlSession sqlSessionFactory.openSession();// 2.获取映射器对象IUserDao userDao sqlSession.getMapper(IUserDao.class);// 3.测试验证User user userDao.queryUserInfoById(1L);logger.info(测试结果{}, JSON.toJSONString(user));
}测试结果 09:17:52.915 [main] INFO c.l.m.d.pooled.PooledDataSource - PooledDataSource forcefully closed/removed all connections.
09:17:53.782 [main] INFO c.l.m.d.pooled.PooledDataSource - Created connention 2104028992.
09:17:53.891 [main] INFO com.lino.mybatis.test.ApiTest - 测试结果{id:1,userHead:1_04,userId:10001,userName:小灵哥}根据单元测试和调试的截图可以看到属性值通过反射的方式设置到对象中满足了我们在创建数据源时的使用。
4.2 反射类测试
4.2.1 学生实体类 Student.java package com.lino.mybatis.test.po;/*** description: 学生类*/
public class Student {private String id;public String getId() {return id;}public void setId(String id) {this.id id;}
}4.2.2 老师实体类 Teacher.java package com.lino.mybatis.test.po;import java.util.List;/*** description: 教师类*/
public class Teacher {private String name;private double price;private ListStudent students;private Student student;public String getName() {return name;}public void setName(String name) {this.name name;}public double getPrice() {return price;}public void setPrice(double price) {this.price price;}public ListStudent getStudents() {return students;}public void setStudents(ListStudent students) {this.students students;}public Student getStudent() {return student;}public void setStudent(Student student) {this.student student;}
}4.2.3 反射类测试 ReflectorTest.java package com.lino.mybatis.test;import com.alibaba.fastjson.JSON;
import com.lino.mybatis.io.Resources;
import com.lino.mybatis.reflection.MetaObject;
import com.lino.mybatis.reflection.SystemMetaObject;
import com.lino.mybatis.session.SqlSession;
import com.lino.mybatis.session.SqlSessionFactory;
import com.lino.mybatis.session.SqlSessionFactoryBuilder;
import com.lino.mybatis.test.dao.IUserDao;
import com.lino.mybatis.test.po.Student;
import com.lino.mybatis.test.po.Teacher;
import com.lino.mybatis.test.po.User;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;/*** description: 反射测试*/
public class ReflectionTest {private Logger logger LoggerFactory.getLogger(ReflectionTest.class);Testpublic void test_reflection() {Teacher teacher new Teacher();ListStudent list new ArrayList();list.add(new Student());teacher.setName(小零哥);teacher.setStudents(list);MetaObject metaObject SystemMetaObject.forObject(teacher);logger.info(getGetterNames{}, JSON.toJSONString(metaObject.getGetterNames()));logger.info(getSetterNames{}, JSON.toJSONString(metaObject.getSetterNames()));logger.info(name的get方法返回值{}, JSON.toJSONString(metaObject.getGetterType(name)));logger.info(students的set方法参数值{}, JSON.toJSONString(metaObject.getGetterType(students)));logger.info(name的hasGetter{}, metaObject.hasGetter(name));logger.info(student.id属性为对象的hasGetter{}, metaObject.hasGetter(student.id));logger.info(获取name的属性值{}, metaObject.getValue(name));// 重新设置属性值metaObject.setValue(name, 哆啦A梦);logger.info(设置name的属性值{}, metaObject.getValue(name));// 设置属性集合的元素值metaObject.setValue(students[0].id, 001);logger.info(获取students集合的第一个元素的属性值{}, JSON.toJSONString(metaObject.getValue(students[0].id)));logger.info(对象的序列化{}, JSON.toJSONString(teacher));}
}测试结果 09:23:10.154 [main] INFO com.lino.mybatis.test.ReflectionTest - getGetterNames[student,price,name,students]
09:23:10.156 [main] INFO com.lino.mybatis.test.ReflectionTest - getSetterNames[student,price,name,students]
09:23:10.156 [main] INFO com.lino.mybatis.test.ReflectionTest - name的get方法返回值java.lang.String
09:23:10.156 [main] INFO com.lino.mybatis.test.ReflectionTest - students的set方法参数值java.util.List
09:23:10.156 [main] INFO com.lino.mybatis.test.ReflectionTest - name的hasGettertrue
09:23:10.157 [main] INFO com.lino.mybatis.test.ReflectionTest - student.id属性为对象的hasGettertrue
09:23:10.157 [main] INFO com.lino.mybatis.test.ReflectionTest - 获取name的属性值小零哥
09:23:10.157 [main] INFO com.lino.mybatis.test.ReflectionTest - 设置name的属性值哆啦A梦
09:23:10.157 [main] INFO com.lino.mybatis.test.ReflectionTest - 获取students集合的第一个元素的属性值001
09:23:10.192 [main] INFO com.lino.mybatis.test.ReflectionTest - 对象的序列化{name:哆啦A梦,price:0.0,students:[{id:001}]}从测试结果看我们拿到了对于的属性信息并可以设置以及修改属性值无论是单个属性还是对象属性都可以操作。
五、总结元对象反射类
关于反射工具类的实现中使用了大量的 JDK 所提供的关于反射一些操作也包括可以获取一个 Class 类中的属性、字段、方法的信息。有了这些信息以后就可以按照功能流程进行解耦把属性、反射、包装都依次拆分出来并按照设计原则逐步包装让外界更少的知道内部的处理。