Mybatis技术内幕(2.3.5):反射模块-Property工具类

基于Mybatis-3.5.0版本java

1.0 property包

org.apache.ibatis.reflection.property包下主要有三个工具类,以下:apache

2.0 PropertyCopier 属性复制器

org.apache.ibatis.reflection.property.PropertyCopier属性复制器,主要用于同一类型两个对象属性复制。代码以下:ide

/** * 属性复制器 * * @author Clinton Begin */
public final class PropertyCopier {

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

	/** * 将 sourceBean 的属性,复制到 destinationBean 中 * @param type 指定类 * @param sourceBean 来源 Bean 对象 * @param destinationBean 目标 Bean 对象 */
	public static void copyBeanProperties(Class<?> type, Object sourceBean, Object destinationBean) {
		Class<?> parent = type;
		// 循环,从当前类开始,不断复制到父类,直到父类不存在
		while (parent != null) {
			// 得到当前 parent 类定义的属性
			final Field[] fields = parent.getDeclaredFields();
			for (Field field : fields) {
				try {
					try {
						// 从 sourceBean 中,复制到 destinationBean 去
						field.set(destinationBean, field.get(sourceBean));
					} catch (IllegalAccessException e) {
						// 设置属性可访问
						if (Reflector.canControlMemberAccessible()) {
							field.setAccessible(true);
							field.set(destinationBean, field.get(sourceBean));
						} else {
							throw e;
						}
					}
				} catch (Exception e) {
					// Nothing useful to do, will only fail on final fields, which will be ignored.
				}
			}
			parent = parent.getSuperclass();
		}
	}
}
复制代码

2.1 PropertyNamer 属性名工具类

org.apache.ibatis.reflection.property.PropertyNamer属性名工具类,主要用来处理getter和setter方法。代码以下:工具

/** * 属性名工具类,主要用来处理getter和setter方法 * @author Clinton Begin */
public final class PropertyNamer {

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

	/** * 根据getter或setter方法获取属性名 * 规则: * 1.java bean getter/setter 方法命名规范截取属性名 * 2.根据驼峰命名法 将第一个字符小写 * @param name * @return */
	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 ReflectionException("Error parsing property name '" + name + "'. Didn't start with 'is', 'get' or 'set'.");
		}

		/** * 若是截取的属性名长度为1或长度大于1且第2位字符是小写 * 例如: * getA -> A -> a * getAA -> AA -> AA */
		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;
	}

	/** * 判断是否为is、get、set方法 * @param name 方法名 * @return */
	public static boolean isProperty(String name) {
		return name.startsWith("get") || name.startsWith("set") || name.startsWith("is");
	}

	/** * 判断是否为 is、get方法 * @param name 方法名 * @return */
	public static boolean isGetter(String name) {
		return name.startsWith("get") || name.startsWith("is");
	}

	/** * 判断是否为set方法 * @param name 方法名 * @return */
	public static boolean isSetter(String name) {
		return name.startsWith("set");
	}
}
复制代码

2.2 PropertyTokenizer 属性分词器

org.apache.ibatis.reflection.property.PropertyTokenizer实现Iterator接口,属性分词器,支持迭代器的访问方式。示例和代码以下:spa

/** * 实现 Iterator 接口,属性分词器,支持迭代器的访问方式 * * @author Clinton Begin */
public class PropertyTokenizer implements Iterator<PropertyTokenizer> {
	// 当前表达式的名称
	private String name;
	// 当前表达式的索引名
	private final String indexedName;
	// 索引下标
	private String index;
	// 子表达式
	private final String children;

	/** * 对传入的表达式,并初始化上面的成员变量 * 例: orders[0].item[0].name * name = orders * indexedName = * orders[0] * children = item[0].name * index = 0 * * @param fullname 待解析的表达式 */
	public PropertyTokenizer(String fullname) {
		// 初始化 name、children 字符串,使用 '.'做为分隔
		int delim = fullname.indexOf('.');
		if (delim > -1) {
			name = fullname.substring(0, delim);
			children = fullname.substring(delim + 1);
		} else {
			name = fullname;
			children = null;
		}
		indexedName = name;
		// 若存在 '[' ,则得到 index ,并修改 name 。
		delim = name.indexOf('[');
		if (delim > -1) {
			// 截取'['与']'中间的字符串
			index = name.substring(delim + 1, name.length() - 1);
			// 截取'['以前的字符串
			name = name.substring(0, delim);
		}
	}

	public String getName() {
		return name;
	}

	public String getIndex() {
		return index;
	}

	public String getIndexedName() {
		return indexedName;
	}

	public String getChildren() {
		return children;
	}

	@Override
	public boolean hasNext() {
		return children != null;
	}

	/** * 迭代方法 建立一个以children为表达式的PropertyTokenizer对象 */
	@Override
	public PropertyTokenizer next() {
		return new PropertyTokenizer(children);
	}

	@Override
	public void remove() {
		throw new UnsupportedOperationException(
				"Remove is not supported, as it has no meaning in the context of properties.");
	}
}
复制代码

3.0 总结

这一节的内容比较简单,不过这个PropertyTokenizer属性分词器的实现仍是颇有意思的。你们在实际的开发中若是有相似的业务场景,也能够考虑这样设计设计

失控的阿甘,乐于分享,记录点滴code

相关文章
相关标签/搜索