本篇主要介绍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();
- }
- }
- }