org.apache.ibatis.reflection.property
包下主要有三个工具类,如下:
org.apache.ibatis.reflection.property.PropertyCopier
属性复制器,主要用于两个对象属性名一致。代码如下:
/** * 属性复制器 * * @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(); } } } 复制代码
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"); } } 复制代码
org.apache.ibatis.reflection.property.PropertyTokenizer
实现Iterator接口,属性分词器,支持迭代器的访问方式。示例和代码如下:
/** * 实现 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."); } } 复制代码