建設網站要編程bu百度代理推廣
歷時漫長的歲月,終于鼓起勇氣繼續(xù)研究Mybatis的反射工具類們,簡直就是把反射玩出花,但是理解起來還是很有難度的,涉及的內容代碼也頗多,所以花費時間也比較浩大,不過當了解套路每個類的功能也好,設計也好,基本也可以濃縮成一句話理解,心中有了系統(tǒng)也好似沒有那么難理解了,本節(jié)如在工作中使用到此場景,可以拿來當作工具直接使用。
前言-為什么使用反射
在手敲Mybatis-數據源池化處理實現那一節(jié),我們留下了坑需要填,在獲取連接時,數據庫連接的設置還是硬編碼,如果我們此時xml文件又需要新增加一些屬性,就需要進行修改代碼,會發(fā)現代碼設計不太靈活,本節(jié)就為了解決此問題,來一起寫一個很強大的反射工具類。

UML類圖-類關系介紹
MyBatis設計將分為以下幾個類,元類、元對象、對象包裝器、反射器、調用者、對象工廠,下面就介紹這幾個設計都是干什么的:
SystemMetaObject:系統(tǒng)入口,萬物的開始,系統(tǒng)級別的元對象
MetaObject:元對象,外部系統(tǒng)調用入口,封裝了包裝器對象,在構造方法中使用策略模式來調用不同的對象包裝器
MetaClass:元類,通過對象包裝器進入,此類是對反射器的封裝并進一步進行處理某些場景復雜操作
Reflector:反射器,解析對象的屬性、方法、類型的解析器,最后組裝起來,提供基礎的方法獲取數據
ObjectWrapper:對象包裝器接口,定義對象基本信息
BaseWrapper:基礎包裝器,抽取共用包裝器方法,解析集合獲取集合設置集合等處理
BeanWrapper:原生包裝器,對bean對象進行處理,由此方法進入MetaClass類最后進入 Reflector反射將對象數據得到。
CollectionWrapper:原生集合包裝器
MapWrapper:map集合包裝器,處理map對象
ObjectWrapperFactory:對象包裝器工廠接口,可以獲取對象包裝器
DefaultObjectWrapperFactory:實現對象包裝器工廠接口
ObjectFactory:對象工廠接口
DefaultObjectFactory:默認對象工廠接口,創(chuàng)建對象實例處理
Invoker: 調用者接口,定義反射調用
MethodInvoker:方法調用者,反射方法的
GetFieldInvoker :此類用于執(zhí)行讀取屬性值的反射操作
SetFieldInvoker:用于執(zhí)行設置屬性值的反射操作
PropertyNamer:屬性命名器,會將方法轉換為屬性名稱
PropertyTokenizer :屬性解析器,屬性也不只有單一屬性也會有復雜屬性,例如屬性.屬性,集合等
執(zhí)行流程:SystemMetaObject-->MetaObject-->ObjectWrapper-->MetaClass-->Reflector-->Invoker
而屬解析器在處理中有時各個類都會用,反射器工具類要用的就這個20個類,想必你通過介紹大大致對它有印象了,可以對應看下uml圖理解理解

完整代碼實現
3.1 反射調用者
package df.middleware.mybatis.reflection.invoker
Invoker:反射調用者接口,定義invoke方法,子類具體實現對應的調用者,因為反射調用離不開目標對象和參數,所以此接口統(tǒng)一定義invoke()。
/*** @description 調用者接口* @date 2022/5/2* 此接口的作用統(tǒng)一基于反射處理方法和屬性的調用方式,采取策略模式*/
public interface Invoker {/*** 執(zhí)行反射操作** @param target 方法或者屬性執(zhí)行的目標對象* @param args 方法或者屬性執(zhí)行時依賴的參數*/Object invoke(Object target, Object[] args) throws Exception;/***方法或者屬性對應的類型*/Class<?> getType();}
MethodInvoker:方法調用者,構造函數會傳對應的目標方method,再通過反射進行調用目標方法
/*** @description 方法調用者* 用于執(zhí)行方法的反射操作*/
public class MethodInvoker implements Invoker {private Class<?> type;private Method method;/*** 如果方法是getter方法,則表示返回值類型* 如果方法是setter方法,則表示入參類型*/public MethodInvoker(Method method) {this.method = method;// 利用方法是否有無入參判斷方法是get還是set方法,// 如果只有一個參數,返回參數類型,否則返回 return 類型if (method.getParameterTypes().length == 1) {// set方法獲取方法入參類型賦給type屬性type = method.getParameterTypes()[0];} else {// get方法則獲取方法返回類型賦給type屬性type = method.getReturnType();}}@Overridepublic Object invoke(Object target, Object[] args) throws Exception {// 執(zhí)行方法return method.invoke(target, args);}@Overridepublic Class<?> getType() {return type;}}
GetFieldInvoker:獲取屬性調用者,構造函數會傳目標屬性Field,通過反射獲取屬性值并返回
/*** @description getter 調用者* 屬性是會有set和get的,所以字段會有GetFieldInvoker和SetFieldInvoker* 此類用于執(zhí)行讀取屬性值的反射操作*/
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();}
}
SetFieldInvoker:設置屬性調用者,構造函數會傳目標屬性Field,通過反射給目標屬性設置值,設置是不返回的,這里就返回空
/*** @description setter 調用者* 用于執(zhí)行設置屬性值的反射操作*/
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[0]);return null;}@Overridepublic Class<?> getType() {return field.getType();}
}
3.2反射器
Reflector:反射器,這個類代碼相對很多,大體主要是用反射將對象信息解析出來,如類里的默認構造方法,以及屬性和方法等等,解析出來處理成我們想要的數據以后存儲各個容器里。這樣我們數據有了,還需要添加一些對外獲取容器數據的公共方法,這就是這個類的全部職責,其實也還好,就是代碼多些,但是知道大致處理內容,也就沒有那么難理解了,需要多debug熟悉。
/*** 反射器,屬性 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 屬性列表,可讀屬性名稱數組,用于保存 getter 方法對應的屬性名稱* */private String[] readablePropertyNames = EMPTY_STRING_ARRAY;/*** set 屬性列表,可寫屬性名稱數組,用于保存 setter 方法對應的屬性名稱* */private String[] writeablePropertyNames = EMPTY_STRING_ARRAY;/*** set 方法列表,* 用于保存屬性名稱到 Invoke 的映射。setter 方法會被封裝到 MethodInvoker 對象中* */private Map<String, Invoker> setMethods = new HashMap<>();/*** get 方法列表* 用于保存屬性名稱到 Invoke 的映射。同上,getter 方法也會被封裝到 MethodInvoker 對象中* */private Map<String, Invoker> getMethods = new HashMap<>();/*** 用于保存 setter 對應的屬性名與參數類型的映射* */private Map<String, Class<?>> setTypes = new HashMap<>();/*** 用于保存 getter 對應的屬性名與返回值類型的映射* */private Map<String, Class<?>> getTypes = new HashMap<>();// 默認構造函數private Constructor<?> defaultConstructor;/*** 用于保存大寫屬性名與屬性名之間的映射,比如 <NAME, name>* */private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();// 解析所有的屬性和方法并把數據處理到全局變量里public Reflector(Class<?> clazz) {this.type = clazz;// 加入構造函數addDefaultConstructor(clazz);// 反射解析getter方法加入 getterMethodsaddGetMethods(clazz);// 反射解析setter方法加入 setterMethods addSetMethods(clazz);// 反射解析字段數據,加入字段addFields(clazz);readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]);writeablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]);for (String propName : readablePropertyNames) {caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);}for (String propName : writeablePropertyNames) {caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);}}private void addDefaultConstructor(Class<?> clazz) {Constructor<?>[] consts = clazz.getDeclaredConstructors();for (Constructor<?> constructor : consts) {if (constructor.getParameterTypes().length == 0) {if (canAccessPrivateMethods()) {try {constructor.setAccessible(true);} catch (Exception ignore) {// Ignored. This is only a final precaution, nothing we can do}}if (constructor.isAccessible()) {this.defaultConstructor = constructor;}}}}private void addGetMethods(Class<?> clazz) {Map<String, List<Method>> conflictingGetters = new HashMap<>();// 獲取類中的方法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);}private void addSetMethods(Class<?> clazz) {Map<String, List<Method>> conflictingSetters = new HashMap<>();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);}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);}}}}// 加入set方法以MethodInvoker放入全局變量里private void addSetMethod(String name, Method method) {if (isValidPropertyName(name)) {setMethods.put(name, new MethodInvoker(method));setTypes.put(name, method.getParameterTypes()[0]);}}private void addFields(Class<?> clazz) {Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {if (canAccessPrivateMethods()) {try {field.setAccessible(true);} catch (Exception e) {// Ignored. This is only a final precaution, nothing we can do.}}if (field.isAccessible()) {if (!setMethods.containsKey(field.getName())) {// issue #379 - removed the check for final because JDK 1.5 allows// modification of final fields through reflection (JSR-133). (JGB)// pr #16 - final static can only be set by the classloaderint 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 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 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);}}}// 加入get方法以MethodInvoker放入全局變量里private void addGetMethod(String name, Method method) {if (isValidPropertyName(name)) {getMethods.put(name, new MethodInvoker(method));getTypes.put(name, method.getReturnType());}}private boolean isValidPropertyName(String name) {return !(name.startsWith("$") || "serialVersionUID".equals(name) || "class".equals(name));}private void addMethodConflict(Map<String, List<Method>> conflictingMethods, String name, Method method) {List<Method> list = conflictingMethods.computeIfAbsent(name, k -> new ArrayList<>());list.add(method);}// 查找當前類及父類方法private Method[] getClassMethods(Class<?> cls) {Map<String, Method> uniqueMethods = new HashMap<String, Method>();Class<?> currentClass = cls;while (currentClass != null) {addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());// we also need to look for interface methods -// because the class may be abstractClass<?>[] interfaces = currentClass.getInterfaces();for (Class<?> anInterface : interfaces) {addUniqueMethods(uniqueMethods, anInterface.getMethods());}currentClass = currentClass.getSuperclass();}Collection<Method> methods = uniqueMethods.values();return methods.toArray(new Method[methods.size()]);}// 校驗方法唯一性,暫存臨時集合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 methodif (!uniqueMethods.containsKey(signature)) {if (canAccessPrivateMethods()) {try {currentMethod.setAccessible(true);} catch (Exception e) {// Ignored. This is only a final precaution, nothing we can do.}}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 static boolean canAccessPrivateMethods() {try {SecurityManager securityManager = System.getSecurityManager();if (null != securityManager) {securityManager.checkPermission(new ReflectPermission("suppressAccessChecks"));}} catch (SecurityException e) {return false;}return true;}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 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 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;}/** Gets the type for a property getter** @param propertyName - the name of the property* @return The Class of the propery getter*/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;}/** Gets an array of the readable properties for an object** @return The array*/public String[] getGetablePropertyNames() {return readablePropertyNames;}/** Gets an array of the writeable properties for an object** @return The array*/public String[] getSetablePropertyNames() {return writeablePropertyNames;}/** Check to see if a class has a writeable property by name** @param propertyName - the name of the property to check* @return True if the object has a writeable property by the name*/public boolean hasSetter(String propertyName) {return setMethods.keySet().contains(propertyName);}/** Check to see if a class has a readable property by name** @param propertyName - the name of the property to check* @return True if the object has a readable property by the name*/public boolean hasGetter(String propertyName) {return getMethods.keySet().contains(propertyName);}public String findPropertyName(String name) {return caseInsensitivePropertyMap.get(name.toUpperCase(Locale.ENGLISH));}/** Gets an instance of ClassInfo for the specified class.* 得到某個類的反射器,是靜態(tài)方法,而且要緩存,又要多線程,所以REFLECTOR_MAP是一個ConcurrentHashMap** @param clazz The class for which to lookup the method cache.* @return The method cache for the class*/public static Reflector forClass(Class<?> clazz) {if (classCacheEnabled) {// synchronized (clazz) removed see issue #461// 對于每個類來說,我們假設它是不會變的,這樣可以考慮將這個類的信息(構造函數,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 void setClassCacheEnabled(boolean classCacheEnabled) {Reflector.classCacheEnabled = classCacheEnabled;}public static boolean isClassCacheEnabled() {return classCacheEnabled;}}
3.3 元類
MetaClass:元類,因為反射器都是基礎的操作,為了方便使用對反射器的進一步封裝,獲取反射器里的容器數據,元類里提供反射器緩存,這樣不用相同的類每次調用都解析處理了,也是補充豐富了反射器基礎的操作,相當于解構一個對象包裝一個元類,而這些元類,包裝器,對象工廠再組合成一個元對象,相當于說這些元類和元對象都是對我們需要操作的原對象解耦后的封裝。有了這樣的操作,就可以讓我們處理每一個屬性或者方法了。
/*** @description 元類* Reflector 反射器類提供的是最基礎的核心功能,很多方法也都是私有的,為了更加方便的使用,* 還需要做一層元類的包裝。在元類 MetaClass 提供必要的創(chuàng)建反射器以及使用反射器獲取* get/set 的 Invoker 反射方法* */
public class MetaClass {// 反射器,用于解析和存儲目標類中的元信息private Reflector reflector;// Reflector.forClass獲取當前類的反射器private 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 String findProperty(String name) {StringBuilder prop = buildProperty(name, new StringBuilder());return prop.length() > 0 ? prop.toString() : null;}public String findProperty(String name, boolean useCamelCaseMapping) {if (useCamelCaseMapping) {name = name.replace("_", "");}return findProperty(name);}public String[] getGetterNames() {return reflector.getGetablePropertyNames();}public String[] getSetterNames() {return reflector.getSetablePropertyNames();}public Class<?> getSetterType(String name) {PropertyTokenizer prop = new PropertyTokenizer(name);if (prop.hasNext()) {MetaClass metaProp = metaClassForProperty(prop.getName());return metaProp.getSetterType(prop.getChildren());} else {return reflector.getSetterType(prop.getName());}}public Class<?> getGetterType(String name) {PropertyTokenizer prop = new PropertyTokenizer(name);if (prop.hasNext()) {MetaClass metaProp = metaClassForProperty(prop);return metaProp.getGetterType(prop.getChildren());}// issue #506. Resolve the type inside a Collection Objectreturn getGetterType(prop);}private MetaClass metaClassForProperty(PropertyTokenizer prop) {Class<?> propType = getGetterType(prop);return MetaClass.forClass(propType);}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);}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 boolean hasDefaultConstructor() {return reflector.hasDefaultConstructor();}}
3.4 對象包裝器
ObjectWapper:對象包裝器接口,定義對象基本操作,獲取對象值、設置對象值、查找屬性、獲取get方法、獲取set方法、屬性類型、添加屬性、設置屬性等等...對象包裝器主要是定義了更加明確的使用方法。
package df.middleware.mybatis.reflection.wrapper
/*** @description 對象包裝器* 是對對象的包裝的接口,抽象了對象的字段信息、 getter| setter 方法、和上面三個成員的數據類型,* 它定義了一系列查詢對象屬性信息的方法,以及更新屬性的方法 。添加屬性方法*/
public interface ObjectWrapper {// getObject get(PropertyTokenizer prop);// setvoid set(PropertyTokenizer prop, Object value);// 查找屬性String findProperty(String name, boolean useCamelCaseMapping);// 取得getter的名字列表String[] getGetterNames();// 取得setter的名字列表String[] getSetterNames();//取得setter的類型Class<?> getSetterType(String name);// 取得getter的類型Class<?> getGetterType(String name);// 是否有指定的setterboolean hasSetter(String name);// 是否有指定的getterboolean hasGetter(String name);// 實例化屬性MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory);// 是否是集合boolean isCollection();// 添加屬性void add(Object element);// 添加屬性<E> void addAll(List<E> element);}
BaseWrapper:基礎對象包裝器,抽象類,實現ObjectWapper,主要是抽取公共代碼,方便由各子類對象包裝器使用,如處理集合則可調用基礎對象包裝器方法即可,此類主要處理解析集合、獲取集合、設置集合中的值
/*** @description 對象包裝器抽象基類,提供一些工具方法* BaseWrapper 抽象類 定義了集合的相關操作。* 1.解析集合* 2.獲取集合中的值* 3.設置集合中的值* */
public abstract class BaseWrapper implements ObjectWrapper {protected static final Object[] NO_ARGUMENTS = new Object[0];protected MetaObject metaObject;protected BaseWrapper(MetaObject metaObject) {this.metaObject = metaObject;}/*** 解析集合*/protected Object resolveCollection(PropertyTokenizer prop, Object object) {if ("".equals(prop.getName())) {return object;} else {return metaObject.getValue(prop.getName());}}/*** 取集合的值* 中括號有2個意思,一個是Map,一個是List或數組*/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.");}}}/*** 設集合的值* 中括號有2個意思,一個是Map,一個是List或數組*/protected void setCollectionValue(PropertyTokenizer prop, Object collection, Object value) {if (collection instanceof Map) {((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.");}}}
}
MapWrapper:Map對象包裝器,是對Map對象的封裝,繼承了 BaseWrapper,構造傳入map類型對象,獲取設置值等等也以map方式即可。
/*** @description Map 包裝器* MapWrapper 是 Map 集合對象的封裝。
*/
public class MapWrapper extends BaseWrapper {// 原來的對象private Map<String, Object> map;public MapWrapper(MetaObject metaObject, Map<String, Object> map) {super(metaObject);this.map = map;}// get,set是允許的,@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) {if (prop.getIndex() != null) {Object collection = resolveCollection(prop, map);setCollectionValue(prop, collection, value);} else {map.put(prop.getName(), value);}}@Overridepublic String findProperty(String name, boolean useCamelCaseMapping) {return name;}@Overridepublic String[] getGetterNames() {return map.keySet().toArray(new String[map.keySet().size()]);}@Overridepublic String[] getSetterNames() {return map.keySet().toArray(new String[map.keySet().size()]);}@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) {HashMap<String, Object> map = new HashMap<String, Object>();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(List<E> element) {throw new UnsupportedOperationException();}
}
CollectionWrapper:Collection對象包裝器,實現ObjectWapper接口,除了添加集合、暫不支持其他操作,拋出異常即可。
/*** @author 小傅哥,微信:fustack* @description Collection 包裝器*/
public class CollectionWrapper implements ObjectWrapper{// 原來的對象private Collection<Object> object;public CollectionWrapper(MetaObject metaObject, Collection<Object> object) {this.object = object;}// get,set都是不允許的,只能添加元素@Overridepublic Object get(PropertyTokenizer prop) {throw new UnsupportedOperationException();}@Overridepublic void set(PropertyTokenizer prop, Object value) {throw new UnsupportedOperationException();}@Overridepublic String findProperty(String name, boolean useCamelCaseMapping) {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(List<E> element) {object.addAll(element);}}
BeanWrapper:原始對象的封裝,自定義對象封裝,繼承BaseWapper,這個是重點,因為是Bean對象,我們需要解析類里屬性以及get,set方法,此時我們需要通過元類進入反射器進行解析,所以BeanWrapper依賴MetaClass
/*** @description Bean 包裝器* BeanWrapper 是原始對象的封裝*/
public class BeanWrapper extends BaseWrapper {// 原來的對象private Object object;// 元類private MetaClass metaClass;public BeanWrapper(MetaObject metaObject, Object object) {super(metaObject);this.object = object;// 通過元類獲取反射器 1個入口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);}}@Overridepublic void set(PropertyTokenizer prop, Object value) {// 如果有index,說明是集合,那就要解析集合,調用的是BaseWrapper.resolveCollection 和 setCollectionValueif (prop.getIndex() != null) {Object collection = resolveCollection(prop, object);setCollectionValue(prop, collection, value);} else {// 否則,setBeanPropertysetBeanProperty(prop, object, value);}}@Overridepublic String findProperty(String name, boolean useCamelCaseMapping) {return metaClass.findProperty(name, useCamelCaseMapping);}@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 (metaClass.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 (metaClass.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.toString(), e);}return metaValue;}@Overridepublic boolean isCollection() {return false;}@Overridepublic void add(Object element) {throw new UnsupportedOperationException();}@Overridepublic <E> void addAll(List<E> list) {throw new UnsupportedOperationException();}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("Could not get property '" + prop.getName() + "' from " + object.getClass() + ". Cause: " + t.toString(), t);}}private void setBeanProperty(PropertyTokenizer prop, Object object, Object value) {try {// 得到setter方法,然后調用Invoker method = metaClass.getSetInvoker(prop.getName());Object[] params = {value};method.invoke(object, params);} catch (Throwable t) {throw new RuntimeException("Could not set property '" + prop.getName() + "' of '" + object.getClass() + "' with value '" + value + "' Cause: " + t.toString(), t);}}
}
3.5 元對象
有了元類,反射器,對象包裝器,最后我們統(tǒng)一一個元對象進行封裝,對外統(tǒng)一調用方式,組成一個完整的元對象操作類。通過構造方法創(chuàng)建不同的對象包裝器,獲取此類中方法則自然調度到不同的wapper包裝器里,實現整條鏈路
/*** @description 元對象* */
public class MetaObject {// 原對象private Object originalObject;/*** 封裝過的 Object 對象*/// 對象包裝器private ObjectWrapper objectWrapper;// 對象工廠private ObjectFactory objectFactory;// 對象包裝工廠private ObjectWrapperFactory objectWrapperFactory;// 賦值為不同的包裝器private 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);}}/*** 創(chuàng)建 MetaObject 對象** @param object 原始 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 ObjectFactory getObjectFactory() {return objectFactory;}public ObjectWrapperFactory getObjectWrapperFactory() {return objectWrapperFactory;}public Object getOriginalObject() {return originalObject;}/* --------以下方法都是委派給 ObjectWrapper------ */// 查找屬性,相當于又封裝了一層public String findProperty(String propName, boolean useCamelCaseMapping) {return objectWrapper.findProperty(propName, useCamelCaseMapping);}/*** 獲取get方法屬性名稱和get方法去掉get后邊的屬性名稱* getIds(){return id;} --> (id、ids)* @return*/// 取得getter的名字列表public String[] getGetterNames() {return objectWrapper.getGetterNames();}/*** 獲取set方法屬性名稱和set方法去掉set后邊的屬性名稱* setIds(){return id;} --> (id、ids)* @return*/// 取得setter的名字列表public String[] getSetterNames() {return objectWrapper.getSetterNames();}/*** 獲取set方法后邊屬性的類型* @param name 這個name 要和setXXX方法中的XXX相同才能獲取到,否則拋異常* @return*/// 取得setter的類型列表public Class<?> getSetterType(String name) {return objectWrapper.getSetterType(name);}/*** 獲取get方法后邊屬性的類型* @param name 這個name,要個getXXX方法中的XXX相同才能獲取到,否則拋異常* @return*/// 取得getter的類型列表public Class<?> getGetterType(String name) {return objectWrapper.getGetterType(name);}/*** 判斷name是否是setXXX()方法中的XXX* @param name* @return*///是否有指定的setterpublic boolean hasSetter(String name) {return objectWrapper.hasSetter(name);}/*** 判斷name是否是getXXX()方法中的XXX* @param name* @return*/// 是否有指定的getterpublic boolean hasGetter(String name) {return objectWrapper.hasGetter(name);}/*** 獲取對象屬性值,可以遞歸獲取* @param name* @return*/// 取得值// 如 班級[0].學生.成績public Object getValue(String name) {// 創(chuàng)建 PropertyTokenizer 對象,對 name 分詞PropertyTokenizer prop = new PropertyTokenizer(name);// 有子表達式if (prop.hasNext()) {// 創(chuàng)建 MetaObject 對象,遞歸調用MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());// 遞歸判斷子表達式 children ,獲取值,metaValue == null,則返回nullif (metaValue == SystemMetaObject.NULL_META_OBJECT) {// 如果上層就是null了,那就結束,返回nullreturn null;} else {// 否則繼續(xù)看下一層,遞歸調用getValuereturn metaValue.getValue(prop.getChildren());}} else {// 無子表達式,取值return objectWrapper.get(prop);}}/*** 給對象屬性設置值,可以遞歸設置,基本類型,數組,對象,都可以自動創(chuàng)建* 但是ArrayList和數組需要手動創(chuàng)建* List必須創(chuàng)建對象,添加進list* @param name* @param value*/// 如 班級[0].學生.成績public void setValue(String name, Object value) {// 創(chuàng)建 PropertyTokenizer 對象,對 name 分詞PropertyTokenizer prop = new PropertyTokenizer(name);// 有子表達式if (prop.hasNext()) {// 創(chuàng)建 MetaObject 對象MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());// 遞歸判斷子表達式 children ,設置值if (metaValue == SystemMetaObject.NULL_META_OBJECT) {if (value == null && prop.getChildren() != null) {// don't instantiate child path if value is null// 如果上層就是 null 了,還得看有沒有兒子,沒有那就結束return;} else {// 創(chuàng)建值// 否則還得 new 一個,委派給 ObjectWrapper.instantiatePropertyValuemetaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);}}// 遞歸調用setValuemetaValue.setValue(prop.getChildren(), value);} else {// 到了最后一層了,所以委派給 ObjectWrapper.setobjectWrapper.set(prop, value);}}// 為屬性生成元對象public MetaObject metaObjectForProperty(String name) {// 實際是遞歸調用Object value = getValue(name);return MetaObject.forObject(value, objectFactory, objectWrapperFactory);}public ObjectWrapper getObjectWrapper() {return objectWrapper;}// 是否是集合public boolean isCollection() {return objectWrapper.isCollection();}// 添加屬性public void add(Object element) {objectWrapper.add(element);}// 添加屬性public <E> void addAll(List<E> list) {objectWrapper.addAll(list);}}
3.6 系統(tǒng)元對象
SystemMetaObject:可通過此類獲取元對象
/*** @description 一些系統(tǒng)級別的元對象*/
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() {// Prevent Instantiation of Static Class}/*** 空對象*/private static class NullObject {}public static MetaObject forObject(Object object) {return MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);}
}
3.7 對象工廠
ObjectFactory:對象工廠接口,創(chuàng)建對象處理
/*** @description 對象工廠接口
*/
public interface ObjectFactory {/*** Sets configuration properties.* 設置屬性* @param properties configuration properties*/void setProperties(Properties properties);/*** Creates a new object with default constructor.* 生產對象* @param type Object type* @return <T>*/<T> T create(Class<T> type);/*** Creates a new object with the specified constructor and params.* 生產對象,使用明確的構造函數和構造函數參數* @param type Object type* @param constructorArgTypes Constructor argument types* @param constructorArgs Constructor argument values* @return <T>*/<T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);/*** Returns true if this object can have a set of other objects.* It's main purpose is to support non-java.util.Collection objects like Scala collections.* 返回這個對象是否是集合,為了支持 Scala collections** @since 3.1.0* @param type Object type* @return whether it is a collection or not*/<T> boolean isCollection(Class<T> type);
}
DefaultObjectFactory:默認對象工廠,實現對象工廠,對象實例化操作,在對象包裝器中復雜場景有子集合對象時進行對象生成操作。
/*** @description 默認對象工廠,所有的對象都有工廠來生成
*/
public class DefaultObjectFactory implements ObjectFactory, Serializable {private static final long serialVersionUID = -8855120656740914948L;@Overridepublic void setProperties(Properties properties) {// no props for default 默認無屬性可設置}@Overridepublic <T> T create(Class<T> type) {return create(type, null, null);}@SuppressWarnings("unchecked")@Overridepublic <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.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[constructorArgTypes.size()]));if (!constructor.isAccessible()) {constructor.setAccessible(true);}return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()]));} 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 argValue : constructorArgs) {argValues.append(argValue);argValues.append(",");}}throw new RuntimeException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e);}}@Overridepublic <T> boolean isCollection(Class<T> type) {return Collection.class.isAssignableFrom(type);}/*** 解析接口,將 interface 轉換為實際的 class 類*/protected 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;}
}
3.8 屬性命名器
/*** @description 屬性命名器* namer 命名者*/
public class PropertyNamer {private PropertyNamer() {}/*** 方法轉換為屬性*/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' or '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的方法*/public static boolean isProperty(String name) {return name.startsWith("get") || name.startsWith("set") || name.startsWith("is");}/*** 是否為 getter*/public static boolean isGetter(String name) {return name.startsWith("get") || name.startsWith("is");}/*** 是否為 setter*/public static boolean isSetter(String name) {return name.startsWith("set");}
}
3.9 屬性分解器
PropertyTokenizer:此類貫穿整個工具使用,主要是解析屬性是不是只是簡單屬性還是復雜屬性,如果有集合,需要解析下標,子集合名稱等操作
/*** @description 屬性分解標記* 可以解析處理簡單屬性以及l(fā)ist集合Map等等的數據* 亮點:可迭代,可以看看*/
public class PropertyTokenizer implements Iterable<PropertyTokenizer>, Iterator<PropertyTokenizer> {// 例子:班級[0].學生.成績// 班級,父表達式private String name;// 班級[0],帶索引的表達式,由父表達式和下標組成private String indexedName;// 0 ,下標,該屬性只對字段類型為map|list|array類型的字段有效,對于list和array類型的字段,index保存的是下標。private String index;// 學生.成績,,子表達式:該屬性只對嵌套表達式有效private String children;public PropertyTokenizer(String fullname) {// 班級[0].學生.成績// 找這個點 .// 解析出parent表達式和children表達式int delim = fullname.indexOf('.');if (delim > -1) {name = fullname.substring(0, delim);//截取到parent表達式children = fullname.substring(delim + 1);//截取到children表達式} else {// 找不到.的話,取全部部分name = fullname;//fullname 即為parent表達式children = null;//無children}indexedName = name;// 把中括號里的數字給解析出來delim = name.indexOf('[');if (delim > -1) {//如果有下標index = name.substring(delim + 1, name.length() - 1);保存下標到indexname = name.substring(0, delim);//3.截取出field name,}}public String getName() {return name;}public String getIndex() {return index;}public String getIndexedName() {return indexedName;}public String getChildren() {return children;}@Overridepublic boolean hasNext() {return children != null;}// 取得下一個,非常簡單,直接再通過兒子來new另外一個實例@Overridepublic PropertyTokenizer next() {return new PropertyTokenizer(children);}@Overridepublic void remove() {throw new UnsupportedOperationException("Remove is not supported, as it has no meaning in the context of properties.");}@Overridepublic Iterator<PropertyTokenizer> iterator() {return this;}
}
3.10 使用反射器數據源屬性設置
那我們先來把UnpooledDataSourceFactory的數據源屬性進行設置
public class UnpooledDataSourceFactory implements DataSourceFactory {protected DataSource dataSource;public UnpooledDataSourceFactory() {this.dataSource = new UnpooledDataSource();}protected Properties pros;@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的類型,將配置文件中的值強轉成相應的類型*/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;}
}
到此我們所有的類都介紹完畢了,我們用單元測試可以測試下,測試準備和上幾節(jié)一樣,可直接運行debug看下通過反射將DataSource的驅動 ,用戶名,密碼等反射設置進來

完事,本節(jié)所有的代碼都已完全展現,大家想要源碼可以去bugStack沖動棧,小傅哥那里