本篇主要介绍mybatis反射工具中用到的三个属性工具类:PropertyTokenizer、PropertyNamer、PropertyCopier。
PropertyTokenizer:
主要用来解析Mybatis使用过程中遇到的类似"order[0].items[0].name"这种由"."和"[ ]"组成的表达式:
public class PropertyTokenizer implements Iterator<PropertyTokenizer> { /** ________________________ * |order[0]|.items[0].name| * ————————————————————————— * * 第一级表达式:name=order;indexName=order[0];index=0;children=item[0].name */ /** * 当前表达式的名称 */ private String name; /** * 当前表达式的索引名 */ private String indexedName; /** * 当前表达式的索引 */ private String index; /** * 子表达式 */ private String children; /** * 初始化上述属性 */ public PropertyTokenizer(String fullname) { 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); } } 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; } @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."); } }
PropertyNamer:
主要是用于实体类中getter、setter方法与相应属性的名称转换和相应的一些检测判断操作:
public final class PropertyNamer { private PropertyNamer() { // Prevent Instantiation of Static Class } /** * get/set方法名转换为相应的属性名称 */ 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'."); } 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方法 */ public static boolean isProperty(String name) { return name.startsWith("get") || name.startsWith("set") || name.startsWith("is"); } /** * 检测方法名是否get方法 */ public static boolean isGetter(String name) { return name.startsWith("get") || name.startsWith("is"); } /** * 检测方法名是否get方法 */ public static boolean isSetter(String name) { return name.startsWith("set"); } }
PropertyCopier:
主要用于相同类型的两个对象之间进行属性值的拷贝:
public final class PropertyCopier { private PropertyCopier() { // Prevent Instantiation of Static Class } public static void copyBeanProperties(Class<?> type, Object sourceBean, Object destinationBean) { Class<?> parent = type; while (parent != null) { /** * 获取到parent中所有被声明的字段,包括public、protected、default、private修饰的,除了 * 继承父类的字段 */ final Field[] fields = parent.getDeclaredFields(); for (Field field : fields) { try { field.setAccessible(true); /** * 将sourceBean的属性值设置到destinationBean中
* set方法也不会将所有的属性值复制,有限制,具体限制可查看set源码 */ field.set(destinationBean, field.get(sourceBean)); } catch (Exception e) { // Nothing useful to do, will only fail on final fields, which will be ignored. } } parent = parent.getSuperclass(); } } }