目录
前言
Mybatis中提供了MetaObject,用来将一个对象的信息通过反射解析出来,保存了对象的元数据,可以通过ognl表达式设置和获取属性。
一、MetaObject的使用
(1)Object类型
可以对对象设置属性值和获取属性值。包括嵌套的属性
@Test
public void testObject() {
Student student = new Student(1L, "stu1", new Address("中国", "北京"));
MetaObject metaObject = SystemMetaObject.forObject(student);
Object name = metaObject.getValue("name");//获取属性值
System.out.println(name);
metaObject.setValue("name", "stu2");//设置属性值
name = metaObject.getValue("name");
System.out.println(name);
Object country = metaObject.getValue("address.country");//是哦那个ognl获取值
System.out.println(country);
}
(2)Collection类型
可以对集合添加元素,不能获取元素,获取方法会抛异常
@Test
public void testCollection() {
Student student1 = new Student(1L, "stu1", new Address("中国", "北京"));
Student student2 = new Student(2L, "stu2", new Address("中国", "上海"));
List<Student> students = new ArrayList<>();
students.add(student1);
MetaObject metaObject = SystemMetaObject.forObject(students);
metaObject.add(student2);//添加元素
System.out.println(students.size());
}
(3)Map类型
可以对map类型添加元素和获取元素
@Test
public void testMap() {
Student student1 = new Student(1L, "stu1", new Address("中国", "北京"));
Student student2 = new Student(2L, "stu2", new Address("中国", "上海"));
Map map = new HashMap();
map.put("student1", student1);
MetaObject metaObject = SystemMetaObject.forObject(map);
metaObject.setValue("student2", student2);//put
System.out.println(map.size());
System.out.println(metaObject.getValue("student2.name"));//get
}
二、MetaObject的原理
1、SystemMetaObject
public final class SystemMetaObject {
//默认对象工厂
public static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
//默认对象包装器工厂
public static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
//空对象的MetaObject
public static final MetaObject NULL_META_OBJECT = MetaObject.forObject(NullObject.class, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
private SystemMetaObject() {
// Prevent Instantiation of Static Class
}
private static class NullObject {
}
public static MetaObject forObject(Object object) {
return MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
}
}
2、MetaObject的构建
(1)MetaObject
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)) {
this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
} else if (object instanceof Map) {
//Map
this.objectWrapper = new MapWrapper(this, (Map) object);
} else if (object instanceof Collection) {
//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);
}
}
(2)MapWrapper
public MapWrapper(MetaObject metaObject, Map<String, Object> map) {
super(metaObject);
//保存传入的map
this.map = map;
}
(3)CollectionWrapper
public CollectionWrapper(MetaObject metaObject, Collection<Object> object) {
//保存传入的Collection
this.object = object;
}
(4)BeanWrapper
public BeanWrapper(MetaObject metaObject, Object object) {
super(metaObject);
this.object = object;
this.metaClass = MetaClass.forClass(object.getClass(), metaObject.getReflectorFactory());
}
forClass( )方法
public static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) {
return new MetaClass(type, reflectorFactory);
}
private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
this.reflectorFactory = reflectorFactory;
this.reflector = reflectorFactory.findForClass(type);
}
DefaultReflectorFactory的findForClass( )方法
public Reflector findForClass(Class<?> type) {
if (classCacheEnabled) {
// synchronized (type) removed see issue #461
//缓存对象的反射信息
return reflectorMap.computeIfAbsent(type, Reflector::new);
} else {
return new Reflector(type);
}
}
创建了一个Reflector对象
public Reflector(Class<?> clazz) {
//类型
type = clazz;
//默认构造方法
addDefaultConstructor(clazz);
//属性的get方法
addGetMethods(clazz);
//属性的set方法
addSetMethods(clazz);
//字段信息
addFields(clazz);
readablePropertyNames = getMethods.keySet().toArray(new String[0]);
writablePropertyNames = setMethods.keySet().toArray(new String[0]);
for (String propName : readablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
for (String propName : writablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
}
3、MetaObject获取值
(1)getValue( )
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);
}
}
metaObjectForProperty
public MetaObject metaObjectForProperty(String name) {
//深度遍历获取子属性的值
Object value = getValue(name);
//为子属性创建MetaObject
return MetaObject.forObject(value, objectFactory, objectWrapperFactory, reflectorFactory);
}
(2)MapWrapper
public Object get(PropertyTokenizer prop) {
if (prop.getIndex() != null) {
//还有下一层级,继续解析
Object collection = resolveCollection(prop, map);
return getCollectionValue(prop, collection);
} else {
//从map中获取值
return map.get(prop.getName());
}
}
protected Object resolveCollection(PropertyTokenizer prop, Object object) {
if ("".equals(prop.getName())) {
return object;
} else {
//解析map的子属性
return metaObject.getValue(prop.getName());
}
}
protected Object getCollectionValue(PropertyTokenizer prop, Object collection) {
if (collection instanceof Map) {
//map
return ((Map) collection).get(prop.getIndex());
} else {
//数组或集合根据下表获取对应的元素
int i = Integer.parseInt(prop.getIndex());
if (collection instanceof List) {
return ((List) collection).get(i);
} else if (collection instanceof Object[]) {
return ((Object[]) collection)[i];
} else if (collection instanceof char[]) {
return ((char[]) collection)[i];
} else if (collection instanceof boolean[]) {
return ((boolean[]) collection)[i];
} else if (collection instanceof byte[]) {
return ((byte[]) collection)[i];
} else if (collection instanceof double[]) {
return ((double[]) collection)[i];
} else if (collection instanceof float[]) {
return ((float[]) collection)[i];
} else if (collection instanceof int[]) {
return ((int[]) collection)[i];
} else if (collection instanceof long[]) {
return ((long[]) collection)[i];
} else if (collection instanceof short[]) {
return ((short[]) collection)[i];
} else {
throw new ReflectionException("The '" + prop.getName() + "' property of " + collection + " is not a List or Array.");
}
}
(3)CollectionWrapper
get方法会抛异常
public Object get(PropertyTokenizer prop) {
throw new UnsupportedOperationException();
}
(4)BeanWrapper
public Object get(PropertyTokenizer prop) {
if (prop.getIndex() != null) {
//如果属性是集合
Object collection = resolveCollection(prop, object);
return getCollectionValue(prop, collection);
} else {
//获取bean的属性值
return getBeanProperty(prop, object);
}
}
private Object getBeanProperty(PropertyTokenizer prop, Object object) {
try {
//找到属性的get方法
Invoker method = metaClass.getGetInvoker(prop.getName());
try {
//反射调用
return method.invoke(object, NO_ARGUMENTS);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
} catch (RuntimeException e) {
throw e;
} catch (Throwable t) {
throw new ReflectionException("Could not get property '" + prop.getName() + "' from " + object.getClass() + ". Cause: " + t.toString(), t);
}
}
public Invoker getGetInvoker(String name) {
//通过reflector获取方法
return reflector.getGetInvoker(name);
}
public Invoker getGetInvoker(String propertyName) {
//根据属性名从缓存的方法中获取到
Invoker method = getMethods.get(propertyName);
if (method == null) {
throw new ReflectionException("There is no getter for property named '" + propertyName + "' in '" + type + "'");
}
return method;
}
4、MetaObject设置值
(1)MetaObject
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);
}
}
(2)MapWrapper
初始化
public MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {
//创建了一个Hashmap
HashMap<String, Object> map = new HashMap<>();
set(prop, map);
return MetaObject.forObject(map, metaObject.getObjectFactory(), metaObject.getObjectWrapperFactory(), metaObject.getReflectorFactory());
}
设置值
public void set(PropertyTokenizer prop, Object value) {
if (prop.getIndex() != null) {
//操作map中的元素
Object collection = resolveCollection(prop, map);
setCollectionValue(prop, collection, value);
} else {
//操作map
map.put(prop.getName(), value);
}
}
(3)CollectionWrapper
初始化和设置值都抛异常
@Override
public MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {
throw new UnsupportedOperationException();
}
@Override
public void set(PropertyTokenizer prop, Object value) {
throw new UnsupportedOperationException();
}
(4)BeanWrapper
初始化
@Override
public MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {
MetaObject metaValue;
Class<?> type = getSetterType(prop.getName());
try {
//使用DefaultObjectFactory初始化对象
Object newObject = objectFactory.create(type);
metaValue = MetaObject.forObject(newObject, metaObject.getObjectFactory(), metaObject.getObjectWrapperFactory(), metaObject.getReflectorFactory());
//设置对象属性
set(prop, newObject);
} catch (Exception e) {
throw new ReflectionException("Cannot set value of property '" + name + "' because '" + name + "' is null and cannot be instantiated on instance of " + type.getName() + ". Cause:" + e.toString(), e);
}
return metaValue;
}
设置值
@Override
public void set(PropertyTokenizer prop, Object value) {
if (prop.getIndex() != null) {
//对集合、map、数组属性设置值
Object collection = resolveCollection(prop, object);
setCollectionValue(prop, collection, value);
} else {
//对bean属性设置值,反射
setBeanProperty(prop, object, value);
}
}
总结
本文主要介绍了MetaObject的使用及原理。