在实现数据源池化时,对于属性信息的获取,采用硬编码的方式。如何采取更好的方式呢?
props.getproperty("driver")
等属性,都是通过手动编码的方式获取的。但是扩展性极差。什么是元对象反射工具类?
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.xml
get/set
属性,包装为可调用的 Invoker 反射类。
get/set
方法反射调用时,使用方法名称获取对应的 invoke 即可 getGetInvoker(String propertyName)
。班级[0].学生.成绩
这样的一个类中的关联类的属性,则需要进行递归的方式拆解处理后,才能设置和获取属性值。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();
}
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();
}
}
@Override
public Object invoke(Object target, Object[] args) throws Exception {
return method.invoke(target, args);
}
@Override
public Class<?> getType() {
return type;
}
}
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;
}
@Override
public Object invoke(Object target, Object[] args) throws Exception {
return field.get(target);
}
@Override
public Class<?> getType() {
return field.getType();
}
}
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;
}
@Override
public Object invoke(Object target, Object[] args) throws Exception {
field.set(target, args);
return null;
}
@Override
public Class<?> getType() {
return field.getType();
}
}
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 + "'. Didn't 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");
}
}
PropertyTokenizer.java
package com.lino.mybatis.reflection.property;
import java.util.Iterator;
/**
* @description: 属性分解标记
*/
public class PropertyTokenizer implements Iterable<PropertyTokenizer>, Iterator<PropertyTokenizer> {
// 例子:班级[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);
}
}
@Override
public Iterator<PropertyTokenizer> iterator() {
return this;
}
@Override
public boolean hasNext() {
return children != null;
}
@Override
public 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;
}
}
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 Map<Class<?>, Reflector> REFLECTOR_MAP = new ConcurrentHashMap<>();
private Class<?> type;
/**
* get 属性列表
*/
private String[] readablePropertyNames = EMPTY_STRING_ARRAY;
/**
* set 属性列表
*/
private String[] writeablePropertyNames = EMPTY_STRING_ARRAY;
/**
* set 方法列表
*/
private Map<String, Invoker> setMethods = new HashMap<>(16);
/**
* get 方法列表
*/
private Map<String, Invoker> getMethods = new HashMap<>(16);
/**
* set 类型列表
*/
private Map<String, Class<?>> setTypes = new HashMap<>(16);
/**
* get 类型列表
*/
private Map<String, Class<?>> getTypes = new HashMap<>(16);
/**
* 构造函数
*/
private Constructor<?> defaultConstructor;
private Map<String, String> caseInsensitivePropertyMap = new HashMap<>(16);
public Reflector(Class<?> clazz) {
this.type = clazz;
// 加入构造函数
addDefaultConstructor(clazz);
// 加入getter
addGetMethods(clazz);
// 加入setter
addSetMethods(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) {
Map<String, List<Method>> 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) {
Map<String, List<Method>> 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(Map<String, List<Method>> conflictingGetters) {
for (String propName : conflictingGetters.keySet()) {
List<Method> getters = conflictingGetters.get(propName);
Iterator<Method> 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(Map<String, List<Method>> conflictingSetters) {
for (String propName : conflictingSetters.keySet()) {
List<Method> 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 {
Iterator<Method> 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) {
Map<String, 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();
}
Collection<Method> methods = uniqueMethods.values();
return methods.toArray(new Method[0]);
}
private void addUniqueMethods(Map<String, 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 method
if (!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(Map<String, List<Method>> conflictingGetters, String name, Method method) {
List<Method> 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) {
// 对于每个类来说,我们假设它是不会变的,这样可以考虑将这个类的信息(构造函数,getter,setter,字段)加入缓存,以提高速度
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;
}
}
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();
}
}
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> void addAll(List<E> elements);
}
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 对象{Map,List/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 对象{Map,List/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.");
}
}
}
}
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());
}
@Override
public Object get(PropertyTokenizer prop) {
// 如果有index(有中括号),说明是集合,那就要解析集合,调用的是 BaseWrapper.resolveCollection 和 getCollectionValue
if (prop.getIndex() != null) {
Object collection = resolveCollection(prop, object);
return getCollectionValue(prop, collection);
} else {
// 否则 getBeanProperty
return 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);
}
}
@Override
public void set(PropertyTokenizer prop, Object value) {
// 如果有index(有中括号),说明是集合,那就要解析集合,调用的是 BaseWrapper.resolveCollection 和 getCollectionValue
if (prop.getIndex() != null) {
Object collection = resolveCollection(prop, object);
setCollectionValue(prop, collection, value);
} else {
// 否则 setBeanProperty
setBeanProperty(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);
}
}
@Override
public String findProperty(String name, boolean useCameCaseMapping) {
return metaClass.findProperty(name, useCameCaseMapping);
}
@Override
public String[] getGetterNames() {
return metaClass.getGetterNames();
}
@Override
public String[] getSetterNames() {
return metaClass.getSetterNames();
}
@Override
public 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);
}
}
@Override
public 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);
}
}
@Override
public 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);
}
}
@Override
public 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);
}
}
@Override
public 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;
}
@Override
public boolean isCollection() {
return false;
}
@Override
public void add(Object element) {
throw new UnsupportedOperationException();
}
@Override
public <E> void addAll(List<E> elements) {
throw new UnsupportedOperationException();
}
}
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 Collection<Object> object;
public CollectionWrapper(MetaObject metaObject, Collection<Object> object) {
this.object = object;
}
@Override
public Object get(PropertyTokenizer prop) {
throw new UnsupportedOperationException();
}
@Override
public void set(PropertyTokenizer prop, Object value) {
throw new UnsupportedOperationException();
}
@Override
public String findProperty(String name, boolean useCameCaseMapping) {
throw new UnsupportedOperationException();
}
@Override
public String[] getGetterNames() {
throw new UnsupportedOperationException();
}
@Override
public String[] getSetterNames() {
throw new UnsupportedOperationException();
}
@Override
public Class<?> getSetterType(String name) {
throw new UnsupportedOperationException();
}
@Override
public Class<?> getGetterType(String name) {
throw new UnsupportedOperationException();
}
@Override
public boolean hasSetter(String name) {
throw new UnsupportedOperationException();
}
@Override
public boolean hasGetter(String name) {
throw new UnsupportedOperationException();
}
@Override
public MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {
throw new UnsupportedOperationException();
}
@Override
public boolean isCollection() {
return true;
}
@Override
public void add(Object element) {
object.add(element);
}
@Override
public <E> void addAll(List<E> elements) {
object.addAll(elements);
}
}
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 Map<String, Object> map;
public MapWrapper(MetaObject metaObject, Map<String, Object> map) {
super(metaObject);
this.map = map;
}
@Override
public Object get(PropertyTokenizer prop) {
// 如果有index(有中括号),说明是集合,那就要解析集合,调用的是 BaseWrapper.resolveCollection 和 getCollectionValue
if (prop.getIndex() != null) {
Object collection = resolveCollection(prop, map);
return getCollectionValue(prop, collection);
} else {
return map.get(prop.getName());
}
}
@Override
public void set(PropertyTokenizer prop, Object value) {
// 如果有index(有中括号),说明是集合,那就要解析集合,调用的是 BaseWrapper.resolveCollection 和 getCollectionValue
if (prop.getIndex() != null) {
Object collection = resolveCollection(prop, map);
setCollectionValue(prop, collection, value);
} else {
// 否则 setBeanProperty
map.put(prop.getName(), value);
}
}
@Override
public String findProperty(String name, boolean useCameCaseMapping) {
return name;
}
@Override
public String[] getGetterNames() {
return map.keySet().toArray(new String[0]);
}
@Override
public String[] getSetterNames() {
return map.keySet().toArray(new String[0]);
}
@Override
public 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;
}
}
}
@Override
public 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;
}
}
}
@Override
public boolean hasSetter(String name) {
return true;
}
@Override
public 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());
}
}
@Override
public MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {
HashMap<String, Object> map = new HashMap<>(16);
set(prop, map);
return MetaObject.forObject(map, metaObject.getObjectFactory(), metaObject.getObjectWrapperFactory());
}
@Override
public boolean isCollection() {
return false;
}
@Override
public void add(Object element) {
throw new UnsupportedOperationException();
}
@Override
public <E> void addAll(List<E> elements) {
throw new UnsupportedOperationException();
}
}
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);
}
DefaultObjectWrapperFactory.java
package com.lino.mybatis.reflection.wrapper;
import com.lino.mybatis.reflection.MetaObject;
/**
* @description: 默认对象包装器
*/
public class DefaultObjectWrapperFactory implements ObjectWrapperFactory {
@Override
public boolean hasWrapperFor(Object object) {
return false;
}
@Override
public ObjectWrapper getWrapperFor(MetaObject metaObject, Object object) {
throw new RuntimeException("The DefaultObjectWrapperFactory should never be called to provide an ObjectWrapper.");
}
}
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 泛型
* @return 泛型对象
*/
<T> T create(Class<T> type);
/**
* 生产对象,使用指定的构造函数和构造函数参数
*
* @param type 对象类型
* @param constructorArgTypes 构造函数
* @param constructorArgs 构造函数参数
* @param 泛型
* @return 泛型对象
*/
<T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);
/**
* 返回这个对象是否是集合
*
* @param type 对象类型
* @param 泛型
* @return 是否是集合
*/
<T> boolean isCollection(Class<T> type);
}
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;
@Override
public void setProperties(Properties properties) {
}
@Override
public <T> T create(Class<T> type) {
return create(type, null, null);
}
@SuppressWarnings("unchecked")
@Override
public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
// 1.解析接口
Class<?> classToCreate = resolveInterface(type);
// 2.类实例化
return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
}
private <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
try {
Constructor<T> constructor;
// 如果没有传入constructor,调用空构造函数,核心是调用 Constructor.newInstance
if (constructorArgTypes == null || constructorArgs == null) {
constructor = type.getDeclaredConstructor();
if (!constructor.isAccessible()) {
constructor.setAccessible(true);
}
return constructor.newInstance();
}
// 如果传入constructor,调用传入的构造函数,核心是调用 Constructor.newInstance
constructor = 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 ---> ArrayList
classToCreate = ArrayList.class;
} else if (type == Map.class) {
// Map ---> HashMap
classToCreate = HashMap.class;
} else if (type == SortedSet.class) {
// SortedSet ---> TreeSet
classToCreate = TreeSet.class;
} else if (type == Set.class) {
// Set ---> HashSet
classToCreate = HashSet.class;
} else {
// 除此之外,就用原来的原型
classToCreate = type;
}
return classToCreate;
}
@Override
public <T> boolean isCollection(Class<T> type) {
return Collection.class.isAssignableFrom(type);
}
}
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类型,则直接赋给objectWrapper
this.objectWrapper = (ObjectWrapper) object;
} else if (objectWrapperFactory.hasWrapperFor(object)) {
// 如果有包装器,调用objectWrapperFactory.getWrapperFor
this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
} else if (object instanceof Map) {
// 如果是Map类型,返回MapWrapper
this.objectWrapper = new MapWrapper(this, (Map) object);
} else if (object instanceof Collection) {
// 如果是Collection类型,返回CollectionWrapper
this.objectWrapper = new CollectionWrapper(this, (Collection) object);
} else {
// 除此之外,返回 BeanWrapper
this.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(List<E> 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,那就结束,返回null
return null;
} else {
// 否则继续看下一层,递归调用getValue
return 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.instantiatePropertyValue
metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);
}
}
// 递归调用setValue
metaValue.setValue(prop.getChildren(), value);
} else {
// 到最后层了,所以委派给 objectWrapper.set
objectWrapper.set(prop, value);
}
}
/**
* 为属性生成元对象
*
* @param name 属性名
* @return 元对象
*/
public MetaObject metaObjectForProperty(String name) {
// 递归调用
Object value = getValue(name);
return MetaObject.forObject(value, objectFactory, objectWrapperFactory);
}
}
getValue(String name)、setValue(String name, Object value)
等。班级[0].学生.成绩
需要被拆解后才能获取到对应的对象和属性值。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
提供元对象的获取。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();
}
@Override
public 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);
}
}
}
@Override
public 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 的元对象,也就是通过反射设置属性值。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();
}
}
ApiTest.java
@Test
public void test_SqlSessionFactoryExecutor() throws IOException {
// 1.从SqlSessionFactory中获取SqlSession
SqlSessionFactory 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":"小灵哥"}
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;
}
}
Teacher.java
package com.lino.mybatis.test.po;
import java.util.List;
/**
* @description: 教师类
*/
public class Teacher {
private String name;
private double price;
private List<Student> 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 List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
}
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);
@Test
public void test_reflection() {
Teacher teacher = new Teacher();
List<Student> 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的hasGetter:true
09:23:10.157 [main] INFO com.lino.mybatis.test.ReflectionTest - student.id(属性为对象)的hasGetter:true
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"}]}