Mybatis技術內幕(2.3.6):反射模組-Wrapper

失控的阿甘發表於2019-03-27

基於Mybatis-3.5.0版本

1.0 Wrapper包

org.apache.ibatis.reflection.wrapper包,如下:

Mybatis技術內幕(2.3.6):反射模組-Wrapper

2.0 ObjectWrapper 物件包裝器介面

org.apache.ibatis.reflection.property.ObjectWrapper物件包裝器介面,基於 MetaClass工具類,定義對指定物件的各種操作。類圖和程式碼如下:

Mybatis技術內幕(2.3.6):反射模組-Wrapper

/**
 * 物件包裝器介面
 * @author Clinton Begin
 */
public interface ObjectWrapper {

	/**
	 * 根據prop獲取物件的屬性值 
	 * 1.如果封裝的是普通的Bean物件,則呼叫相應屬性的getter方法
	 * 2.如果封裝的集合類,則獲取指定key或下標對應的value
	 * @param prop PropertyTokenizer分詞器物件
	 * @return
	 */
	Object get(PropertyTokenizer prop);

	/**
	 * 根據prop設定物件的屬性值
	 * 1.如果封裝的是普通的Bean物件,則呼叫相應屬性的setter方法
	 * 2.如果封裝的集合類,則設定指定key或下標對應的value
	 * @param prop	PropertyTokenizer分詞器物件
	 * @param value 要設定的值
	 */
	void set(PropertyTokenizer prop, Object value);

	/**
	 * 查詢屬性表示式指定的屬性,第二個參數列示是否忽略屬性表示式中的下劃線
	 * @param name	名稱
	 * @param useCamelCaseMapping 是否開啟駝峰命名對映
	 * @return
	 */
	String findProperty(String name, boolean useCamelCaseMapping);
	
	/**
	 * 獲取物件的可讀屬性陣列
	 * @return
	 */
	String[] getGetterNames();
	
	/**
	 * 獲取物件的可寫屬性陣列
	 * @return
	 */
	String[] getSetterNames();
	
	/**
	 * 根據屬性表示式獲取對應的setter方法的引數型別
	 * @param name
	 * @return
	 */
	Class<?> getSetterType(String name);
	
	/**
	 * 根據屬性表示式獲取對應的getter方法的返回值型別
	 * @param name
	 * @return
	 */
	Class<?> getGetterType(String name);
	
	/**
	 * 是否有該屬性表示式對應的setter方法
	 * @param name
	 * @return
	 */
	boolean hasSetter(String name);
	/**
	 * 是否有該屬性表示式對應的getter方法
	 * @param name
	 * @return
	 */
	boolean hasGetter(String name);
	
	/**
	 * 根據屬性表示式例項化物件,並set到當前物件
	 * 主要作用於初始化物件屬性也是物件的場景
	 * @param name
	 * @param prop
	 * @param objectFactory
	 * @return
	 */
	MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory);

	/**
	 * 是否是集合
	 * @return
	 */
	boolean isCollection();

	/**
	 * 新增元素到集合
	 * @param element
	 */
	void add(Object element);
	
	/**
	 * 批量新增到集合
	 * @param element
	 */
	<E> void addAll(List<E> element);
}
複製程式碼

2.1 BaseWrapper 基礎包裝器

org.apache.ibatis.reflection.wrapper.BaseWrapper抽象類,實現ObjectWrapper介面,為子類BeanWrapper和MapWrapper提供公共的方法和屬性。程式碼如下:

/**
 * 抽象類,實現ObjectWrapper介面
 * 為子類BeanWrapper和MapWrapper提供公共的方法和屬性
 * @author Clinton Begin
 */
public abstract class BaseWrapper implements ObjectWrapper {
	// 無引數物件,主要用於執行getter方法所需
	protected static final Object[] NO_ARGUMENTS = new Object[0];
	// metaObject物件
	protected final MetaObject metaObject;

	protected BaseWrapper(MetaObject metaObject) {
		this.metaObject = metaObject;
	}

	/**
	 * 處理集合:
	 * 根據PropertyTokenizer獲取對應屬性的集合(Array、List、Map)物件
	 *
	 * @param prop   PropertyTokenizer 物件
	 * @param object 指定 Object 物件
	 * @return 值
	 */
	protected Object resolveCollection(PropertyTokenizer prop, Object object) {
		if ("".equals(prop.getName())) {
			return object;
		} else {
			return metaObject.getValue(prop.getName());
		}
	}

	/**
	 * 根據PropertyTokenizer獲取集合(Array、List、Map)的值
	 * @param prop PropertyTokenizer 物件
	 * @param collection 集合(Array、List、Map)
	 * @return 對應下標或key的值
	 */
	protected Object getCollectionValue(PropertyTokenizer prop, Object collection) {
		if (collection instanceof Map) {
			// 如果是Map型別,則index為key
			return ((Map) collection).get(prop.getIndex());
		} else {
			// 如果是其他集合型別,則index為下標
			int i = Integer.parseInt(prop.getIndex());
			if (collection instanceof List) {
				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 {
				// 不是集合物件拋ReflectionException異常
				throw new ReflectionException(
						"The '" + prop.getName() + "' property of " + collection + " is not a List or Array.");
			}
		}
	}

	/**
	 * 根據PropertyTokenizer設定集合(Array、List、Map)的值
	 * @param prop PropertyTokenizer 物件
	 * @param collection 集合(Array、List、Map)
	 * @param value 值
	 */
	protected void setCollectionValue(PropertyTokenizer prop, Object collection, Object value) {
		if (collection instanceof Map) {
			// 如果是Map型別,則index為key
			((Map) collection).put(prop.getIndex(), value);
		} else {
			// 如果是其他集合型別,則index為下標
			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 {
				// 不是集合物件拋ReflectionException異常
				throw new ReflectionException(
						"The '" + prop.getName() + "' property of " + collection + " is not a List or Array.");
			}
		}
	}
}
複製程式碼

2.2 BeanWrapper 普通物件包裝器

org.apache.ibatis.reflection.wrapper.BeanWrapper普通物件包裝器,繼承BaseWrapper類,基於MetaClass實現對Object的屬性操作。程式碼如下:

/**
 * 繼承BaseWrapper,普通Bean包裝器。
 * @author Clinton Begin
 */
public class BeanWrapper extends BaseWrapper {
	// 封裝的物件
	private final Object object;
	// 封裝的物件對應的MetaClass物件
	private final MetaClass metaClass;

	public BeanWrapper(MetaObject metaObject, Object object) {
		super(metaObject);
		this.object = object;
		this.metaClass = MetaClass.forClass(object.getClass(), metaObject.getReflectorFactory());
	}

	@Override
	public Object get(PropertyTokenizer prop) {
		// 存在索引資訊,則表示該屬性表示式中的name部分為集合型別
		if (prop.getIndex() != null) {
			// 通過BaseWrapper中的公共方法獲取集合物件和集合屬性
			Object collection = resolveCollection(prop, object);
			return getCollectionValue(prop, collection);
		} else {
			// 不存在索引資訊,則name部分為普通物件,查詢並呼叫Invoker相關方法獲取屬性
			return getBeanProperty(prop, object);
		}
	}

	@Override
	public void set(PropertyTokenizer prop, Object value) {
		// 存在索引資訊,則表示該屬性表示式中的name部分為集合型別
		if (prop.getIndex() != null) {
			// 通過BaseWrapper中的公共方法獲取集合物件,然後設定集合屬性
			Object collection = resolveCollection(prop, object);
			setCollectionValue(prop, collection, value);
		} else {
			// 不存在索引資訊,則name部分為普通物件,查詢並呼叫Invoker相關方法設定屬性
			setBeanProperty(prop, object, value);
		}
	}

	@Override
	public String findProperty(String name, boolean useCamelCaseMapping) {
		return metaClass.findProperty(name, useCamelCaseMapping);
	}

	@Override
	public String[] getGetterNames() {
		return metaClass.getGetterNames();
	}

	@Override
	public String[] getSetterNames() {
		return metaClass.getSetterNames();
	}

	@Override
	public Class<?> getSetterType(String name) {
		// 根據屬性表示式建立PropertyTokenizer物件
		PropertyTokenizer prop = new PropertyTokenizer(name);
		if (prop.hasNext()) {
			// 有子表示式,根據indexedName建立MetaObject物件
			MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
			// 對應的屬性值為null
			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物件
		PropertyTokenizer prop = new PropertyTokenizer(name);
		if (prop.hasNext()) {
			// 有子表示式,根據indexedName建立MetaObject物件
			MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
			// 對應的屬性值為null
			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物件
		PropertyTokenizer prop = new PropertyTokenizer(name);
		if (prop.hasNext()) {
			if (metaClass.hasSetter(prop.getIndexedName())) {
				// 有子表示式,根據indexedName建立MetaObject物件
				MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
				// 對應的屬性值為null
				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物件
		PropertyTokenizer prop = new PropertyTokenizer(name);
		if (prop.hasNext()) {
			if (metaClass.hasGetter(prop.getIndexedName())) {
				// 有子表示式,根據indexedName建立MetaObject物件
				MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
				// 對應的屬性值為null
				if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
					return metaClass.hasGetter(name);
				} else {
					return metaValue.hasGetter(prop.getChildren());
				}
			} else {
				return false;
			}
		} else {
			// 沒有子表示式
			return metaClass.hasGetter(name);
		}
	}

	/**
	 * 主要針對巢狀屬性的場景
	 * 即 address.street address.city時
	 * address 也是一個物件,且未初始化
	 * 首次設定address初始化相關物件並賦值到相關屬性
	 */
	@Override
	public MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {
		MetaObject metaValue;
		// 獲得 setter 方法的方法引數型別
		Class<?> type = getSetterType(prop.getName());
		try {
			// 建立物件
			Object newObject = objectFactory.create(type);
			// 建立 MetaObject 物件
			metaValue = MetaObject.forObject(newObject, metaObject.getObjectFactory(),
					metaObject.getObjectWrapperFactory(), metaObject.getReflectorFactory());
			// 設定當前物件的值
			set(prop, newObject);
		} catch (Exception e) {
			throw new ReflectionException("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;
	}

	/**
	 * 獲取Object對應PropertyTokenizer的屬性值
	 * @param prop	PropertyTokenizer物件
	 * @param object
	 * @return
	 */
	private Object getBeanProperty(PropertyTokenizer prop, Object object) {
		try {
			// 根據屬性名稱,查詢Reflector.getMethods集合中相應的GetFieldInvoker或MethodInvoker
			Invoker method = metaClass.getGetInvoker(prop.getName());
			try {
				// 獲取屬性值
				return method.invoke(object, NO_ARGUMENTS);
			} catch (Throwable t) {
				throw ExceptionUtil.unwrapThrowable(t);
			}
		} catch (RuntimeException e) {
			throw e;
		} catch (Throwable t) {
			throw new ReflectionException("Could not get property '" + prop.getName() + "' from " + object.getClass()
					+ ".  Cause: " + t.toString(), t);
		}
	}

	/**
	 * 設定Object對應PropertyTokenizer的屬性值
	 * @param prop
	 * @param object
	 * @param value
	 */
	private void setBeanProperty(PropertyTokenizer prop, Object object, Object value) {
		try {
			// 根據屬性名稱,查詢Reflector.setMethods集合中相應的SetFieldInvoker或MethodInvoker
			Invoker method = metaClass.getSetInvoker(prop.getName());
			Object[] params = { value };
			try {
				// 設定屬性值
				method.invoke(object, params);
			} catch (Throwable t) {
				throw ExceptionUtil.unwrapThrowable(t);
			}
		} catch (Throwable t) {
			throw new ReflectionException("Could not set property '" + prop.getName() + "' of '" + object.getClass()
					+ "' with value '" + value + "' Cause: " + t.toString(), t);
		}
	}

	@Override
	public boolean isCollection() {
		return false;
	}

	@Override
	public void add(Object element) {
		throw new UnsupportedOperationException();
	}

	@Override
	public <E> void addAll(List<E> list) {
		throw new UnsupportedOperationException();
	}
}
複製程式碼

2.3 MapWrapper Map物件包裝器

org.apache.ibatis.reflection.wrapper.MapWrapperMap物件包裝器,繼承BaseWrapper類,基於java.util.Map介面方法實現對屬性的操作。程式碼如下:

/**
 * Map 物件包裝器
 * @author Clinton Begin
 */
public class MapWrapper extends BaseWrapper {
	// 封裝的Map物件
	private final Map<String, Object> map;

	public MapWrapper(MetaObject metaObject, Map<String, Object> map) {
		super(metaObject);
		this.map = map;
	}

	@Override
	public Object get(PropertyTokenizer prop) {
		// 存在索引資訊,則表示該屬性表示式中的name部分為集合型別
		if (prop.getIndex() != null) {
			// 通過BaseWrapper中的公共方法獲取集合物件和集合屬性
			Object collection = resolveCollection(prop, map);
			return getCollectionValue(prop, collection);
		} else {
			// 不存在索引資訊,則name部分為普通物件,直接從Map中獲取值
			return map.get(prop.getName());
		}
	}

	@Override
	public void set(PropertyTokenizer prop, Object value) {
		// 存在索引資訊,則表示該屬性表示式中的name部分為集合型別
		if (prop.getIndex() != null) {
			// 通過BaseWrapper中的公共方法獲取集合物件並設定集合屬性
			Object collection = resolveCollection(prop, map);
			setCollectionValue(prop, collection, value);
		} else {
			// 不存在索引資訊,則name部分為普通物件,直接Map.put設定值
			map.put(prop.getName(), value);
		}
	}

	@Override
	public String findProperty(String name, boolean useCamelCaseMapping) {
		return name;
	}

	@Override
	public String[] getGetterNames() {
		return map.keySet().toArray(new String[map.keySet().size()]);
	}

	@Override
	public String[] getSetterNames() {
		return map.keySet().toArray(new String[map.keySet().size()]);
	}

	@Override
	public Class<?> getSetterType(String name) {
		// 根據屬性表示式建立PropertyTokenizer物件
		PropertyTokenizer prop = new PropertyTokenizer(name);
		if (prop.hasNext()) {
			// 有子表示式,根據indexedName建立MetaObject物件
			MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
			// 對應的屬性值為null
			if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
				return Object.class;
			} else {
				// 子表示式由MetaObject處理
				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物件
		PropertyTokenizer prop = new PropertyTokenizer(name);
		if (prop.hasNext()) {
			// 有子表示式,根據indexedName建立MetaObject物件
			MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
			// 對應的屬性值為null
			if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
				return Object.class;
			} else {
				// 子表示式由MetaObject處理
				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物件
		PropertyTokenizer prop = new PropertyTokenizer(name);
		if (prop.hasNext()) {
			if (map.containsKey(prop.getIndexedName())) {
				// 有子表示式,根據indexedName建立MetaObject物件
				MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
				// 對應的屬性值為null
				if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
					return true;
				} else {
					// 子表示式由MetaObject處理
					return metaValue.hasGetter(prop.getChildren());
				}
			} else {
				return false;
			}
		} else {
			// 沒有子表示式
			return map.containsKey(prop.getName());
		}
	}

	/**
	 * 主要針對巢狀屬性的場景
	 * 即 address.street address.city時
	 * 首次設定address會建立一個 key為address value為new HashMap<>()
	 */
	@Override
	public MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {
		// 建立Map
		HashMap<String, Object> map = new HashMap<>();
		// 設定值
		set(prop, map);
		// 返回封裝map的MetaObject物件
		return MetaObject.forObject(map, metaObject.getObjectFactory(), metaObject.getObjectWrapperFactory(),
				metaObject.getReflectorFactory());
	}

	@Override
	public boolean isCollection() {
		return false;
	}

	@Override
	public void add(Object element) {
		throw new UnsupportedOperationException();
	}

	@Override
	public <E> void addAll(List<E> element) {
		throw new UnsupportedOperationException();
	}
}
複製程式碼

2.4 CollectionWrapper

org.apache.ibatis.reflection.wrapper.CollectionWrapperCollection物件包裝器,直接實現ObjectWrapper介面。程式碼如下:

/**
 * 集合包裝器
 * @author Clinton Begin
 */
public class CollectionWrapper implements ObjectWrapper {

	// 封裝的集合物件
	private final 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 useCamelCaseMapping) {
		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> element) {
		object.addAll(element);
	}
}
複製程式碼

3.0 ObjectWrapperFactory 物件包裝器工廠

org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory物件包裝器工廠介面。類圖和程式碼如下:

Mybatis技術內幕(2.3.6):反射模組-Wrapper

/**
 * 物件包裝器工廠
 * @author Clinton Begin
 */
public interface ObjectWrapperFactory {

	/**
	 * 是否包裝了指定物件
	 * @param object 指定物件
	 * @return 是否
	 */
	boolean hasWrapperFor(Object object);

	/**
	 * 獲得指定物件的 ObjectWrapper 物件
	 * @param metaObject MetaObject 物件
	 * @param object     指定物件
	 * @return ObjectWrapper 物件
	 */
	ObjectWrapper getWrapperFor(MetaObject metaObject, Object object);
}
複製程式碼

3.1 DefaultObjectWrapperFactory

org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory實現ObjectWrapperFactory介面。程式碼如下:

/**
 * @author Clinton Begin
 */
public class DefaultObjectWrapperFactory implements ObjectWrapperFactory {

	@Override
	public boolean hasWrapperFor(Object object) {
		return false;
	}

	@Override
	public ObjectWrapper getWrapperFor(MetaObject metaObject, Object object) {
		throw new ReflectionException(
				"The DefaultObjectWrapperFactory should never be called to provide an ObjectWrapper.");
	}
}
複製程式碼

3.2 ObjectWrapperFactory擴充套件點

可以看到DefaultObjectWrapperFactory並未做任何功能性的設計,但是Mybatis提供了基於mybatis-config配置的擴充套件。配置如下:

<!-- mybatis-config.xml -->
<objectWrapperFactory type="org.apache.ibatis.builder.ExampleObjectWrapperFactory"/>
複製程式碼

4.0 MetaClass和MetaObject

Wrapper包裝器的大部分功能都是委託MetaClass和MetaObject物件實現的,現在來具體看下它們的實現。

4.1 MetaClass 類的後設資料

org.apache.ibatis.reflection.MetaClass類的後設資料,基於Reflector和PropertyTokenizer組合使用,實現了對複雜的屬性表示式的解析。程式碼如下:

/**
 * 類的後設資料
 * 基於Reflector和PropertyTokenizer組合使用,實現了對複雜的屬性表示式的解析
 * 
 * @author Clinton Begin
 */
public class MetaClass {
	// Reflector工廠類 預設DefaultReflectorFactory
	private final ReflectorFactory reflectorFactory;
	// 反射器,在建立MetaClass時會指定一個類,該Reflector物件用於記錄該類相關的元資訊
	private final Reflector reflector;

	private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
		this.reflectorFactory = reflectorFactory;
		this.reflector = reflectorFactory.findForClass(type);
	}

	/**
	 * 靜態方法建立MetaClass物件
	 * @param type	指定類
	 * @param reflectorFactory	指定ReflectorFactory
	 * @return
	 */
	public static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) {
		return new MetaClass(type, reflectorFactory);
	}

	/**
	 * 建立類的指定屬性名的類的 MetaClass物件
	 * @param name
	 * @return
	 */
	public MetaClass metaClassForProperty(String name) {
		Class<?> propType = reflector.getGetterType(name);
		return MetaClass.forClass(propType, reflectorFactory);
	}

	/**
	 * 根據屬性表示式獲取屬性名
	 * @param name
	 * @return
	 */
	public String findProperty(String name) {
		// 委託給buildProperty()方法實現
		StringBuilder prop = buildProperty(name, new StringBuilder());
		return prop.length() > 0 ? prop.toString() : null;
	}

	/**
	 * (過載)根據屬性表示式獲取屬性名
	 * @param name
	 * @param useCamelCaseMapping 是否使用駝峰命名對映 即去除"_"字元
	 * @return
	 */
	public String findProperty(String name, boolean useCamelCaseMapping) {
		if (useCamelCaseMapping) {
			name = name.replace("_", "");
		}
		return findProperty(name);
	}

	/**
	 * 獲取指定類的可讀屬性陣列
	 * @return
	 */
	public String[] getGetterNames() {
		return reflector.getGetablePropertyNames();
	}

	/**
	 * 獲取指定類的可寫屬性陣列
	 * @return
	 */
	public String[] getSetterNames() {
		return reflector.getSetablePropertyNames();
	}

	/**
	 * 通過表示式 找到對應屬性 的setter方法引數型別
	 * @param name
	 * @return
	 */
	public Class<?> getSetterType(String name) {
		PropertyTokenizer prop = new PropertyTokenizer(name);
		if (prop.hasNext()) {
			MetaClass metaProp = metaClassForProperty(prop.getName());
			return metaProp.getSetterType(prop.getChildren());
		} else {
			return reflector.getSetterType(prop.getName());
		}
	}

	public Class<?> getGetterType(String name) {
		PropertyTokenizer prop = new PropertyTokenizer(name);
		if (prop.hasNext()) {
			MetaClass metaProp = metaClassForProperty(prop);
			return metaProp.getGetterType(prop.getChildren());
		}
		// issue #506. Resolve the type inside a Collection Object
		return getGetterType(prop);
	}

	/**
	 * 根據PropertyTokenizer構建MetaClass物件
	 * @param prop
	 * @return
	 */
	private MetaClass metaClassForProperty(PropertyTokenizer prop) {
		// 獲取屬性型別
		Class<?> propType = getGetterType(prop);
		return MetaClass.forClass(propType, reflectorFactory);
	}

	/**
	 * 獲取getter型別,如果prop有下標且為集合則獲取泛型型別
	 * 例:
	 * private List<String> list;
	 * List<String> getList();
	 * prop list 返回 java.util.List;
	 * prop list[0] 返回 java.lang.String;
	 * @param prop
	 * @return
	 */
	private Class<?> getGetterType(PropertyTokenizer prop) {
		// 獲得返回型別
		Class<?> type = reflector.getGetterType(prop.getName());
		// 如果屬性表示式有index 且 屬性是集合型別
		if (prop.getIndex() != null && Collection.class.isAssignableFrom(type)) {
			// 獲取集合的泛型型別
			Type returnType = getGenericGetterType(prop.getName());
			if (returnType instanceof ParameterizedType) {
				Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments();
				// Collection<T>最多隻有一個泛型
				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 invoker = reflector.getGetInvoker(propertyName);
			if (invoker instanceof MethodInvoker) {
				Field _method = MethodInvoker.class.getDeclaredField("method");
				_method.setAccessible(true);
				Method method = (Method) _method.get(invoker);
				// 解析Method獲取返回型別
				return TypeParameterResolver.resolveReturnType(method, reflector.getType());
			} else if (invoker instanceof GetFieldInvoker) {
				Field _field = GetFieldInvoker.class.getDeclaredField("field");
				_field.setAccessible(true);
				Field field = (Field) _field.get(invoker);
				// 解析Field獲取引數型別
				return TypeParameterResolver.resolveFieldType(field, reflector.getType());
			}
		} catch (NoSuchFieldException | IllegalAccessException ignored) {
		}
		return null;
	}

	public boolean hasSetter(String name) {
		// 解析屬性表示式 ,建立PropertyTokenizer物件
		PropertyTokenizer prop = new PropertyTokenizer(name);
		if (prop.hasNext()) {// 有子表示式
			// 父級屬性名有setter方法
			if (reflector.hasSetter(prop.getName())) {
				// 根據父級屬性型別構建MetaClass物件,遞迴操作
				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物件
		PropertyTokenizer prop = new PropertyTokenizer(name);
		if (prop.hasNext()) {// 有子表示式
			// 父級屬性名有getter方法
			if (reflector.hasGetter(prop.getName())) {
				// 根據父級屬性型別構建MetaClass物件,遞迴操作
				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);
	}

	/**
	 * 
	 * @param name
	 * @param builder
	 * @return
	 */
	private StringBuilder buildProperty(String name, StringBuilder builder) {
		// 解析屬性表示式
		PropertyTokenizer prop = new PropertyTokenizer(name);
		if (prop.hasNext()) {// 有子表示式
			String propertyName = reflector.findPropertyName(prop.getName());
			if (propertyName != null) {
				builder.append(propertyName);
				builder.append(".");
				// 為該屬性建立對應的MetaClass物件
				MetaClass metaProp = metaClassForProperty(propertyName);
				// 遞迴解析PropertyTokenizer.children欄位,並將解析結果新增到builder中儲存
				metaProp.buildProperty(prop.getChildren(), builder);
			}
		} else {// 沒有子表示式
			// 忽略屬性名的大小寫
			String propertyName = reflector.findPropertyName(name);
			if (propertyName != null) {
				builder.append(propertyName);
			}
		}
		return builder;
	}

	/**
	 * 判斷該類是否有預設無參構造器
	 * @return
	 */
	public boolean hasDefaultConstructor() {
		return reflector.hasDefaultConstructor();
	}
}
複製程式碼

4.2 MetaObject 物件的後設資料

org.apache.ibatis.reflection.MetaObject物件的後設資料,Mybatis物件操作的工具類,等同於MetaClass。提供了基於對複雜的屬性表示式為物件的屬性值的獲得和設定等方法。程式碼如下:

/**
 * 物件後設資料
 * Mybatis物件操作的工具類,等同於MetaClass
 * 提供了基於對複雜的屬性表示式為物件的屬性值的獲得和設定等方法。
 * 通過組合的方式(封裝ObjectWrapper),對BaseWrapper操作進一步增強。
 * 
 * @author Clinton Begin
 */
public class MetaObject {
	// 原始物件
	private final Object originalObject;
	// 包裝過的物件
	private final ObjectWrapper objectWrapper;
	// 物件工廠
	private final ObjectFactory objectFactory;
	// 物件包裝器工廠
	private final ObjectWrapperFactory objectWrapperFactory;
	// 反射器工廠
	private final ReflectorFactory reflectorFactory;

	private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory,
			ReflectorFactory reflectorFactory) {
		this.originalObject = object;
		this.objectFactory = objectFactory;
		this.objectWrapperFactory = objectWrapperFactory;
		this.reflectorFactory = reflectorFactory;

		// 根據object型別,建立對應的Wrapper物件
		if (object instanceof ObjectWrapper) {
			this.objectWrapper = (ObjectWrapper) object;
		} else if (objectWrapperFactory.hasWrapperFor(object)) {
			this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
		} else if (object instanceof Map) {
			this.objectWrapper = new MapWrapper(this, (Map) object);
		} else if (object instanceof Collection) {
			this.objectWrapper = new CollectionWrapper(this, (Collection) object);
		} else {
			this.objectWrapper = new BeanWrapper(this, object);
		}
	}

	/**
	 * 靜態的MetaObject建立方法
	 * @param object
	 * @param objectFactory
	 * @param objectWrapperFactory
	 * @param reflectorFactory
	 * @return
	 */
	public static MetaObject forObject(Object object, ObjectFactory objectFactory,
			ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
		if (object == null) {
			// object為null,建立預設的SystemMetaObject.NULL_META_OBJECT
			return SystemMetaObject.NULL_META_OBJECT;
		} else {
			return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
		}
	}

	public ObjectFactory getObjectFactory() {
		return objectFactory;
	}

	public ObjectWrapperFactory getObjectWrapperFactory() {
		return objectWrapperFactory;
	}

	public ReflectorFactory getReflectorFactory() {
		return reflectorFactory;
	}

	public Object getOriginalObject() {
		return originalObject;
	}

	public String findProperty(String propName, boolean useCamelCaseMapping) {
		return objectWrapper.findProperty(propName, useCamelCaseMapping);
	}

	public String[] getGetterNames() {
		return objectWrapper.getGetterNames();
	}

	public String[] getSetterNames() {
		return objectWrapper.getSetterNames();
	}

	public Class<?> getSetterType(String name) {
		return objectWrapper.getSetterType(name);
	}

	public Class<?> getGetterType(String name) {
		return objectWrapper.getGetterType(name);
	}

	public boolean hasSetter(String name) {
		return objectWrapper.hasSetter(name);
	}

	public boolean hasGetter(String name) {
		return objectWrapper.hasGetter(name);
	}

	public Object getValue(String name) {
		// 根據屬性表示式建立PropertyTokenizer物件
		PropertyTokenizer prop = new PropertyTokenizer(name);
		if (prop.hasNext()) {
			// 有子表示式,根據indexedName建立MetaObject物件
			MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
			// 遞迴判斷子表示式 children ,獲取值
			if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
				return null;
			} else {
				return metaValue.getValue(prop.getChildren());
			}
		} else {
			return objectWrapper.get(prop);
		}
	}

	public void setValue(String name, Object value) {
		// 根據屬性表示式建立PropertyTokenizer物件
		PropertyTokenizer prop = new PropertyTokenizer(name);
		if (prop.hasNext()) {
			// 有子表示式,根據indexedName建立MetaObject物件
			MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
			// 如果對應的屬性值為null
			if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
				if (value == null) {
					// don't instantiate child path if value is null
					return;
				} else {
					// 呼叫對應的objectWrapper初始化屬性值
					metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);
				}
			}
			// 遞迴判斷子表示式 children ,設定值
			metaValue.setValue(prop.getChildren(), value);
		} else {
			objectWrapper.set(prop, value);
		}
	}

	/**
	 * 根據屬性表示式獲取屬性值,然後建立MetaObject物件
	 * @param name
	 * @return
	 */
	public MetaObject metaObjectForProperty(String name) {
		Object value = getValue(name);
		return MetaObject.forObject(value, objectFactory, objectWrapperFactory, reflectorFactory);
	}

	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);
	}
}
複製程式碼

4.3 SystemMetaObject

org.apache.ibatis.reflection.SystemMetaObject系統級的MetaObject物件。程式碼如下:

public final class SystemMetaObject {

	// DefaultObjectFactory 的單例
	public static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
	// DefaultObjectWrapperFactory的單例
	public static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
	// 空物件的 MetaObject 物件單例
	public static final MetaObject NULL_META_OBJECT = MetaObject.forObject(NullObject.class, DEFAULT_OBJECT_FACTORY,
			DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());

	private SystemMetaObject() {
		// Prevent Instantiation of Static Class
	}

	private static class NullObject {}

	/**
	 * 建立 MetaObject 物件
	 *
	 * @param object 指定物件
	 * @return MetaObject 物件
	 */
	public static MetaObject forObject(Object object) {
		return MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY,
				new DefaultReflectorFactory());
	}
}
複製程式碼

5.0 總結

這一章的內容比較重要,涉及到ORM框架的核心即物件關係對映,簡單點講就是將SQL查詢到的資料轉換為JavaBean的過程。本章的程式碼沒有很複雜,程式碼量也是不很大。但是程式碼的執行軌跡和要實際解決的場景還是比較複雜,需要大家跟著相應的Test類一點一點跟進,去理解不同場景的執行過程。這樣才能更好的理解作者的設計思路。

失控的阿甘,樂於分享,記錄點滴

相關文章