MetaObject是Mybatis一个反射工具类,进行了高度封装,根据属性进行获取值,设置值,支持对象的嵌套这种结构
objectWrapper 是获取当前对象的属性值,不支持对象的嵌套
MetaClass 支持子属性的获取
Reflector 就是直接使用反射获取值,或者设置值,相当于一层一层的进行封装上来的,我们从上而下进行看
虽然我们今天是主要看MetaOject但是只看这一个类就没啥看头了,和ObjectWrapper 结合起来一起看
//原始对象
private final Object originalObject;
//包装对象
private final ObjectWrapper objectWrapper;
private final ObjectFactory objectFactory;
private final ObjectWrapperFactory objectWrapperFactory;
private final ReflectorFactory reflectorFactory;
几个属性 我们主要关心 objectWrapper,其他的几个工厂类全部默认的就可以,代码基本没有啥也;
private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
this.originalObject = object;
this.objectFactory = objectFactory;
this.objectWrapperFactory = objectWrapperFactory;
this.reflectorFactory = reflectorFactory;
if (object instanceof ObjectWrapper) { //原始对象本身就是包装类
this.objectWrapper = (ObjectWrapper) object;
} else if (objectWrapperFactory.hasWrapperFor(object)) { //默认是返回fase 除非我们自己定义 objectWrapperFactory
this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
} else if (object instanceof Map) { // 原始类属于map
this.objectWrapper = new MapWrapper(this, (Map) object);
} else if (object instanceof Collection) { // 原始类属于集合
this.objectWrapper = new CollectionWrapper(this, (Collection) object);
} else { //普通的bean对象
this.objectWrapper = new BeanWrapper(this, object);
}
}
构造方法私有化
public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
if (object == null) {
return SystemMetaObject.NULL_META_OBJECT;
} else {
return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
}
}
通过这个forObject获取MetaObject对象,如果传入的原始对象是null,则返回一个SystemMetaObject
public Object getValue(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
return null;
} else {
return metaValue.getValue(prop.getChildren());
}
} else {
return objectWrapper.get(prop);
}
}
public void setValue(String name, Object value) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
if (value == null) {
// don't instantiate child path if value is null
return;
} else {
metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);
}
}
metaValue.setValue(prop.getChildren(), value);
} else {
objectWrapper.set(prop, value);
}
}
最核心的两个方法,后面一起将流程
这是老师讲课使用的一个例子
自己写了一个例子:ps:这种问题自己多进行debug感觉比看这种图有用:
public static void main(String[] args) {
Address address = new Address();
address.setTon("address1");
Address address2 = new Address();
address2.setTon("address2");
Student stu = new Student();
stu.setAddress(address);
stu.setName("张三");
stu.setAge(12);
Student stu2 = new Student();
stu2.setAddress(address2);
stu2.setName("张三");
stu2.setAge(12);
ClassRoom classRoom = new ClassRoom();
classRoom.setNo(1);
ArrayList students = new ArrayList<>();
students.add(stu);
students.add(stu2);
classRoom.setStudentList(students);
Map tags = new HashMap<>();
tags.put("一班","优秀班级");
classRoom.setTags(tags);
MetaObject metaObject = MetaObject.forObject(classRoom, new DefaultObjectFactory(), new DefaultObjectWrapperFactory(), new DefaultReflectorFactory());
Object value = metaObject.getValue("no");
System.out.println(value);
Object value1 = metaObject.getValue("studentList[0].address.ton");
System.out.println(value1);
Object tags1 = metaObject.getValue("tags");
System.out.println(tags1);
}
Object value1 = metaObject.getValue(“studentList[0].address.ton”);
我们拿这个来描述其中运行的逻辑吧:
ps:
studentList[0] 这个获取第一个元素值的时候,首先利用name获取到该属性的集合,再利用indexedName,获取第几个元素,这样就可以直接获取到集合中第几个元素的值
public class PropertyTokenizer implements Iterator {
//属性名称
private String name;
//属性名称➕索引 主要是集合属性 eg: user[0]
private final String indexedName;