抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

MYBATIS反射模块

Invoker包

这个包中对Java的反射调用进行了二次封装,定义了一个Invoker接口和三个具体实现。我们首先来看Invoker接口

Invoker接口

这个接口定义了两个函数,invoke用来执行具体的调用,getType用来返回调用对象的具体的类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* Invoker接口
* @author Clinton Begin
*/
public interface Invoker {
/**
* 调用接口
* @param target 目标对象
* @param args 参数
* @return
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;

/**
* 获取类型
* @return
*/
Class<?> getType();
}

GetFieldInvoker类

这两个类都实现了Invoker接口,都有一个类型为java.lang.reflect.Field的属性,这个属性在初始化时进行设置。

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/**
* 获取字段中的值
* @author Clinton Begin
*/
public class GetFieldInvoker implements Invoker {
//具体字段定义
private final Field field;

/**
* 构造方法
* @param field
*/
public GetFieldInvoker(Field field) {
this.field = field;
}

/**
* 调用方法
* @param target 目标对象
* @param args 参数
* @return
* @throws IllegalAccessException
*/
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException {
try {
//获取字段的值
return field.get(target);
//如果是私有的
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
//如果是私有的使用暴力反射
field.setAccessible(true);
return field.get(target);
} else {
throw e;
}
}
}

/**
* 获取字段的类型
* @return
*/
@Override
public Class<?> getType() {
return field.getType();
}
}

SetFieldInvoker和GetFieldInvoker类

这两个类都实现了Invoker接口,都有一个类型为java.lang.reflect.Field的属性,这个属性在初始化时进行设置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 构造方法
* @param field
*/
public SetFieldInvoker(Field field) {
this.field = field;
}

/**
* 构造方法
* @param field
*/
public GetFieldInvoker(Field field) {
this.field = field;
}

getType函数返回的是Field的类型:

1
2
3
4
5
6
7
8
/**
* 获取字段的类型
* @return
*/
@Override
public Class<?> getType() {
return field.getType();
}

这两个类最大的不同在于对invoke函数的实现上,一个是调用fieldd的set方法,一个是调用Field的get方法。

获取字段的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 调用方法
* @param target 目标对象
* @param args 参数
* @return
* @throws IllegalAccessException
*/
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException {
try {
//获取字段的值
return field.get(target);
//如果是私有的
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
//如果是私有的使用暴力反射
field.setAccessible(true);
return field.get(target);
} else {
throw e;
}
}
}
设置字段的值
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
/**
* 具体调用
* @param target 目标对象
* @param args 参数
* @return
* @throws IllegalAccessException
*/
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException {
try {
//设置字段值
field.set(target, args[0]);
//如果是private
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
//使用暴力反射
field.setAccessible(true);
field.set(target, args[0]);
} else {
throw e;
}
}
return null;
}

MethodInvoker类

这个类相对前面两个类要复杂些,主要复杂的地方在于type的确定,这个type的确定是在构造函数中进行的

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/**
* 方法调用的封装
*
* @author Clinton Begin
*/
public class MethodInvoker implements Invoker {
//参数类型
private final Class<?> type;
//基础属性 method
private final Method method;

/**
* 构造方法
*
* @param method
*/
public MethodInvoker(Method method) {
this.method = method;
//method的类型不像Field的类型那样,如果这个method有参数,就取第一个参数的类型;如果没有参数就取这个method的返回值
if (method.getParameterTypes().length == 1) {
type = method.getParameterTypes()[0];
} else {
type = method.getReturnType();
}
}

/**
* 具体方法的调用
*
* @param target 目标对象
* @param args 参数
* @return
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
try {
//通过反射进行调用
return method.invoke(target, args);
//如果是私有属性
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
//设置暴力反射
method.setAccessible(true);
return method.invoke(target, args);
} else {
throw e;
}
}
}

/**
* 获取参数类型
* @return
*/
@Override
public Class<?> getType() {
return type;
}
}

property包

property包主要来操作对象的属性的

PropertyCopier类

属性复制器,这个类就是就是将一个对象的属性值赋给另一个对象中对应的属性。

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**
* 属性复制器
*
* @author Clinton Begin
*/
public final class PropertyCopier {

private PropertyCopier() {
// Prevent Instantiation of Static Class
}

/**
* 将 sourceBean 的属性,复制到 destinationBean 中
*
* @param type 指定类型
* @param sourceBean 来源 Bean 对象
* @param destinationBean 目标 Bean 对象
*/
public static void copyBeanProperties(Class<?> type, Object sourceBean, Object destinationBean) {
Class<?> parent = type;
// 循环,从当前类开始,不断复制到父类,直到父类不存在
while (parent != null) {
// 获得当前 parent 类定义的属性
final Field[] fields = parent.getDeclaredFields();
for (Field field : fields) {
try {
try {
// 从 sourceBean 中,复制到 destinationBean 去
field.set(destinationBean, field.get(sourceBean));
//如果是私有的
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
// 设置属性可访问
field.setAccessible(true);
//属性复制
field.set(destinationBean, field.get(sourceBean));
} else {
throw e;
}
}
} catch (Exception e) {
// Nothing useful to do, will only fail on final fields, which will be ignored.
}
}
//设置父类给parent
parent = parent.getSuperclass();
}
}

}

PropertyNamer类

属性名工具类,主要用来处理getter和setter方法

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/**
* 属性名工具类,主要用来处理getter和setter方法
*
* @author Clinton Begin
*/
public final class PropertyNamer {

private PropertyNamer() {
// Prevent Instantiation of Static Class
}

/**
* 根据getter或setter方法获取属性名
* 规则:
* 1.java bean getter/setter 方法命名规范截取属性名
* 2.根据驼峰命名法 将第一个字符小写
*
* @param name
* @return
*/
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'.");
}
/**
* 如果截取的属性名长度为1或长度大于1且第2位字符是小写
* 例如:
* getA -> A -> a
* getAA -> AA -> AA
*/
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;
}

/**
* 判断是否为is、get、set方法
*
* @param name
* @return
*/
public static boolean isProperty(String name) {
return isGetter(name) || isSetter(name);
}

//判断是否为 is、get方法
public static boolean isGetter(String name) {
return (name.startsWith("get") && name.length() > 3) || (name.startsWith("is") && name.length() > 2);
}

/**
* 判断是否为set方法
* @param name
* @return
*/
public static boolean isSetter(String name) {
return name.startsWith("set") && name.length() > 3;
}

}

PropertyTokenizer类

这个类是property包中的重量级类,该类会被reflection包中其他的类频繁的引用到。这个类实现了Iterable和Iterator这两个接口,但在使用时经常被用到的是Iterator接口中的hasNext这个函数

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/**
* 属性分词器
* 实现 Iterator 接口,属性分词器,支持迭代器的访问方式
*
* @author Clinton Begin
*/
public class PropertyTokenizer implements Iterator<PropertyTokenizer> {
// 当前表达式的名称
private String name;
// 当前表达式的索引名
private final String indexedName;
// 索引下标
private String index;
// 子表达式
private final String children;

/**
* 对传入的表达式,并初始化上面的成员变量
* 例: orders[0].item[0].name
* name = orders
* indexedName =
* orders[0]
* children = item[0].name
* index = 0
* @param fullname 待解析的表达式
*/
public PropertyTokenizer(String fullname) {
// 初始化 name、children 字符串,使用 '.'作为分隔
int delim = fullname.indexOf('.');
if (delim > -1) {
name = fullname.substring(0, delim);
children = fullname.substring(delim + 1);
} else {
name = fullname;
children = null;
}
indexedName = name;
// 若存在 '[' ,则获得 index ,并修改 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;
}

/**
* 经常使用的hasNext函数实现比较简单,就是判断children属性是不是为空
* @return
*/
@Override
public boolean hasNext() {
return children != null;
}

/**
* 迭代方法 创建一个以children为表达式的PropertyTokenizer对象
* @return
*/
@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.");
}
}

评论