上述提到的都是”属性“,而不是字段。按照JavaBean的规范,类中定义的成员变量称为“ 宇段” ,属性则是通过ge阳r/setter 方法得到的,属性只与类中的方法有关,与是否存在对应成员变量没有关系。
所以,Mybatis与对应DO进行交互的依据是getter/setter方法。所以,可以通过自定义getter/setter方法进行字段转换。另外,DO中有字段,但没有对应getter/setter方法,则无法在对应mapper进行映射,最终导致报错。
MetaClass
MetaClass 是MyBatis 对类级别的元信息的封装和处理。
MetaClass 通过Reflector 和PropertyTokenizer 组合使用, 实现了对复杂的属性表达式的解析,并实现了获取指定属性描述信息的功能。
/**
* @author Clinton Begin
*/
public class MetaClass {
private final ReflectorFactory reflectorFactory;
// class对应等Reflector
private final Reflector reflector;
private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
this.reflectorFactory = reflectorFactory;
this.reflector = reflectorFactory.findForClass(type);
}
// 核心方法:解析属性表达式。委托给buildProperty方法实现
public String findProperty(String name) {
StringBuilder prop = buildProperty(name, new StringBuilder());
return prop.length() > 0 ? prop.toString() : null;
}
private StringBuilder buildProperty(String name, StringBuilder builder) {
// name即是属性表达式。如<result property= ”orders[0].items[1].name” column= ”item2” />
// PropertyTokenizer包含name、indexName、index、children
PropertyTokenizer prop = new PropertyTokenizer(name);
// 判断是否还有子表达式
if (prop.hasNext()) {
String propertyName = reflector.findPropertyName(prop.getName());
if (propertyName != null) {
// 返回结果,追加属性名(.name形式)
builder.append(propertyName);
builder.append(".");
// 为该属性,建立对应的MetaClass
MetaClass metaProp = metaClassForProperty(propertyName);
// 深度优先递归。创建所有MetaClass,并通过builder形成一个深度优先遍历的关系链
metaProp.buildProperty(prop.getChildren(), builder);
}
} else {
String propertyName = reflector.findPropertyName(name);
if (propertyName != null) {
builder.append(propertyName);
}
}
return builder;
}
}
ObjectWrapper
ObjectWrapper接口是对对象的包装,抽象了对象的属性信息,定义了一系列查询对象属性信息的方法,以及更新属性的方法。
其功能实现,是通过实现基础类-BaseObjectWrapper,委托给MetaObject实现。
/**
* @author Clinton Begin
*/
public interface ObjectWrapper {
// 如采Object Wrapper 中封装的是普通的Bean对象,则调用相应属性的相应getter 方法
// 如采封装的是集合类,则获取指定key或下标对应的value值
Object get(PropertyTokenizer prop);
void set(PropertyTokenizer prop, Object value);
// 查找属性表达式指定的属性,第二个参数表示是否忽略属性表达式中的下画线
String findProperty(String name, boolean useCamelCaseMapping);
String[] getGetterNames();
String[] getSetterNames();
// 解析属性表达式指定属性的setter 方法的参数类型。name为请求的属性表达式
Class<?> getSetterType(String name);
Class<?> getGetterType(String name);
boolean hasSetter(String name);
boolean hasGetter(String name);
// 为属性表达式指定的属性创建相应的MetaObject对象
MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory);
boolean isCollection();
void add(Object element);
<E> void addAll(List<E> element);
}
MetaObject