0%

mybatis的MetaObject反射工具类

mybatis的MetaObject反射工具类

MetaObjectmybatis中用于处理反射相关的工具类,通过MetaObject就可以进行获取和设置对象值。

简单使用

简单类型:

1
2
3
4
5
6
7
8
9
10
11
@Test
public void testMetaObject(){
// 创建一个Blog对象
Object blog = new Blog();
Configuration configuration = new Configuration();
// 使用默认配置创建一个MetaObject对象
MetaObject metaObject = configuration.newMetaObject(blog);
// 直接为Blog的id属性赋值
metaObject.setValue("id", 1);
System.out.println(metaObject.getValue("id"));
}

复杂类型:

1
2
3
4
5
6
7
8
9
@Test
public void testMetaObject(){
Object blog = new Blog();
Configuration configuration = new Configuration();
MetaObject metaObject = configuration.newMetaObject(blog);
// 为Bolg中的对象赋值,如果对象为空,会通过该对象的构造函数创建一个空对象
metaObject.setValue("author.name", "tommy");
System.out.println(metaObject.getValue("author.name"));
}

集合类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
public void testMetaObject(){
Object blog = new Blog();
Configuration configuration = new Configuration();
MetaObject metaObject = configuration.newMetaObject(blog);
List<Comment> commentList = new ArrayList<>(5);
// 尽管设置了数组长度为5,以下调用还是报错,原因是set(index, value)方法中有判断
// 若 index >= size 则报越界,而size只有add(value)方法会进行叠加
//commentList.set(0,new Comment());
commentList.add(new Comment());
// 1.如果是Object对象,为空时会通过构造函数进行创建,但是集合不能自动创建
// 2.setValue的底层是调用集合的List.set(index, value)方法,不是List.add方法,所以要注意数组越界
metaObject.setValue("comments", commentList);
metaObject.setValue("comments[0]", new Comment());
System.out.println(metaObject.getValue("comments[0].user.name"));
}

结构

主要由MetaObjectObjectWrapperMetaClassReflector构成。

MetaObject.png

1.MetaObject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class MetaObject {
// 原始对象
private final Object originalObject;
// 包装对象,根据不同对象的不同类型进行包装
private final ObjectWrapper objectWrapper;
private final ObjectFactory objectFactory;
private final ObjectWrapperFactory objectWrapperFactory;
private final ReflectorFactory reflectorFactory;
}
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) {
this.objectWrapper = new MapWrapper(this, (Map) object);
} else if (object instanceof Collection) {
this.objectWrapper = new CollectionWrapper(this, (Collection) object);
} else {
this.objectWrapper = new BeanWrapper(this, object);
}
}

创建完MetaObject之后,从MetaObject调用的setValuegetValue等属性操作方法实际上都委派给了ObjectWrapper进行处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public Object getValue(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
// 如果存在下一层表达式,则创建下一层MetaObject
if (prop.hasNext()) {
MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
return null;
} else {
// 通过创建的下一层的MetaObject对象,再次调用getValue,进入递归
return metaValue.getValue(prop.getChildren());
}
} else {
// 不存在下一层表达式,通过wrapper对象进行反射获取值
return objectWrapper.get(prop);
}
}

2.ObjectWrapper

ObjectWrapper是顶层接口,定义了wrapper包装原始对象的处理接口,如果原始对象是Bean对象那么具体的获取属性等操作在BeanWrapper,如果原始对象是Map则通过MapWrapper进行实现具体的属性操作,同理List则通过CollectionWrapper进行实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public interface ObjectWrapper {

Object get(PropertyTokenizer prop);

void set(PropertyTokenizer prop, Object value);

String findProperty(String name, boolean useCamelCaseMapping);

String[] getGetterNames();

String[] getSetterNames();

Class<?> getSetterType(String name);

Class<?> getGetterType(String name);

boolean hasSetter(String name);

boolean hasGetter(String name);

MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory);

boolean isCollection();

void add(Object element);

<E> void addAll(List<E> element);
}

BeanWrapperMapWrapper是继承于抽象类BaseWrapper,由抽象类继承顶层接口ObjectWrapperCollectionWrapper是直接继承于顶层接口。这是因为如果原始对象是集合,它仅有addaddAll操作,其他接口均抛异常。

在BeanWrapper中解析表达式为词法分析器后进行属性操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 以set方法为例,通过PropertyTokenizer词法分析器,对比如“comment[0].user.id”进行解析
@Override
public void set(PropertyTokenizer prop, Object value) {
if (prop.getIndex() != null) {
Object collection = resolveCollection(prop, object);
setCollectionValue(prop, collection, value);
} else {
setBeanProperty(prop, object, value);
}
}
private void setBeanProperty(PropertyTokenizer prop, Object object, Object value) {
try {
// 获取到对象的set方法
Invoker method = metaClass.getSetInvoker(prop.getName());
Object[] params = {value};
try {
// 通过反射赋值
method.invoke(object, params);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
} catch (Throwable t) {
// ...
}
}

PropertyTokenizer:词法分析器,实现迭代器接口,通过next()方法解析下一层。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 这里以 comments[0].user.id为例
public class PropertyTokenizer implements Iterator<PropertyTokenizer> {
// 表示当前层的名字: comments
private String name;
// 若是集合则为comments[0],否则indexedName和name值一致
private final String indexedName;
// 表示下标: 若不是集合或者Map,则为空
private String index;
// 表示子表达式: user.id
private final String children;

@Override
public boolean hasNext() {
return children != null;
}

@Override
public PropertyTokenizer next() {
return new PropertyTokenizer(children);
}
}

3.MetaClass

1
2
3
4
5
6
7
8
9
10
11
public class MetaClass {

private final ReflectorFactory reflectorFactory;
private final Reflector reflector;

private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
this.reflectorFactory = reflectorFactory;
// 通过这个反射工厂来创建一个反射器
this.reflector = reflectorFactory.findForClass(type);
}
}

ReflectorFactory这个反射工厂的主要作用是对Reflector反射器进行缓存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class DefaultReflectorFactory implements ReflectorFactory {
private boolean classCacheEnabled = true;
// 缓存
private final ConcurrentMap<Class<?>, Reflector> reflectorMap = new ConcurrentHashMap<>();

@Override
public Reflector findForClass(Class<?> type) {
if (classCacheEnabled) {
// 如果缓存中存在,则直接返回
return reflectorMap.computeIfAbsent(type, Reflector::new);
} else {
return new Reflector(type);
}
}
}

4.Reflector

根据创建的Class对象,解析出这个类的所有getset方法,构造函数,所有属性字段等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Reflector {

private final Class<?> type;
private final String[] readablePropertyNames;
private final String[] writablePropertyNames;
private final Map<String, Invoker> setMethods = new HashMap<>();
private final Map<String, Invoker> getMethods = new HashMap<>();
private final Map<String, Class<?>> setTypes = new HashMap<>();
private final Map<String, Class<?>> getTypes = new HashMap<>();
private Constructor<?> defaultConstructor;

private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();

public Reflector(Class<?> clazz) {
type = clazz;
addDefaultConstructor(clazz);
addGetMethods(clazz);
addSetMethods(clazz);
addFields(clazz);
readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]);
writablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]);
for (String propName : readablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
for (String propName : writablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
}
}
-------------本文结束感谢您的阅读-------------