# 一.joor 简单介绍
# 1.功能介绍
- 提供 on()操作符对类名、Class、Object 进行统一实例化为 Reflect 对象,后续所有的反射操作基于该 Reflect 对象。
- 有功能调用方式均被封装成返回 Reflect 对象的链式结构,在使用上使得代码更加简洁。
- 对方法的签名匹配封装了更完善的匹配规则,包括精确匹配 exactMethod()、近似匹配 similarMethod()【对函数参数的近似匹配(int -> Integer)】和基类搜索等。
- 调用私有方法的不需要显示调用 setAccessible(),内部动态读取 public 标记自动适配。
- 更加简洁的实现了对象构造函数的反射调用 create()方法。
- 函数的调用 call()方法组合成了可以拼接在 Reflect 的对象后面的链式方法。
- 额外增加了高级操作符 as(),它实现了类的代理访问以及 POJO 对象的 get/set/is 方法实现。
# 2.和传统反射优势
从上面的例子就可以看到 jOOR 明显的优势:
- 简化了反射冗长的异常处理
- 简化了对 Class、Method、Field、Constructor 反射类的实例化,改为统一 Reflect 替换
- 支持 private 方法的调用,内部动态区分是否需要 accessible()
- 将反射调用封装为更流行的链式调用方式,代码更容易理解(类似 Rxjava 的封装方式)
- 支持类型内部 wrap 转换(泛型实现)
# 3.安装依赖
joor 优雅的进行反射,使用 joor 可以简化代码,可以捕捉到使用反射时无法抛出的异常
<!-- https://mvnrepository.com/artifact/org.jooq/joor -->
<dependency>
<groupId>org.jooq</groupId>
<artifactId>joor</artifactId>
<version>0.9.6</version>
</dependency>
1
2
3
4
5
6
2
3
4
5
6
# 二.使用
# 1.api 介绍
/**
* https://github.com/jOOQ/jOOR
* Reflect实际是对原生java reflect进行封装,屏蔽了无关细节。
*
* Reflect.create 用来调用之前的类的构造方法,有两种重载,一种有参数,一种无参数
* Reflect.call 方法调用,传入方法名和参数,如有返回值还需要调用get
* Reflect.get 获取(field和method返回)值相关,会进行类型转换,常与call和field组合使用
* Reflect.field 获取属性值相关,需要调用get获取该值
* Reflect.set 设置属性相关。
*/
//1、通过类名转换成一个Reflect对象:
public static Reflect on(String name);
public static Reflect on(String name, ClassLoader classLoader);
public static Reflect on(Class<?> clazz);
//2、将一个类对象转换成一个Reflect对象:
public static Reflect on(Object object);
//3、修改一个AccessibleObject类型的对象的访问权限:
public static <T extends AccessibleObject> T accessible(T accessible);
//4、返回Reflect对象具体包装的类型,类型为Class或者对象,由操作符on()的重载参数决定:
public <T> T get();
//5、将name指定的field转换成一个Reflect对象,后续对field的操作变为对Reflect对象的操作:
public Reflect field(String name);
//6、返回当前Reflect对象的所有field属性,并转换成Reflect对象的map:
public Map<String, Reflect> fields();
//7、修改(获取)field属性值:
public Reflect set(String name, Object value);
public <T> T get(String name);
//8、反射调用name指定的函数,此函数封装了对函数的签名的精准匹配和近似匹配:
public Reflect call(String name);
public Reflect call(String name, Object... args);
//9、反射调用指定类的构造函数,也封装了精准匹配和近似匹配:
public Reflect create();
public Reflect create(Object... args);
//10、返回当前Reflect对象封装的对象类型:
public Class<?> type();
//11、给封装对象创建一个代理访问,还实现了对POJO对象的setXX/getXX/isxx功能(此为Reflect对象的高级功能):
public <P> P as(Class<P> proxyType);
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
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
# 2.简单示例
// All examples assume the following static import:
import static org.joor.Reflect.*;
String world = on("java.lang.String") // on后面放入类的全名,这里是String类
.create("Hello World") // 将字符串“Hello World”,传入构造方法中
.call("substring", 6) // 执行subString这个方法,并且传入6作为参数
.call("toString") // 执行toString方法
.get(); // 得到包装好的类,这里是一个String对象
// 使用joor赋值
ABC abc1 = new ABC();
on(abc1).set("A","123").set("B","321");
System.out.println(abc1);// ABC(A=123, B=321)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 3.复杂示例
String name = null;
Kale kale;
// 【创建类】
kale = Reflect.on(Kale.class).create().get(); // 无参数
kale = Reflect.on(Kale.class).create("kale class name").get();// 有参数
System.err.println("------------------> class name = " + kale.getClassName());
// 【调用方法】
Reflect.on(kale).call("setName","调用setName");// 多参数
System.err.println("调用方法:name = " + Reflect.on(kale).call("getName"));// 无参数
// 【得到变量】
name = Reflect.on(kale).field("name").get();// 复杂
name = Reflect.on(kale).get("name");// 简单
System.err.println("得到变量值: name = " + name);
// 【设置变量的值】
Reflect.on(kale).set("className", "hello");
System.err.println("设置变量的值: name = " + kale.getClassName());
System.err.println("设置变量的值: name = " + Reflect.on(kale).set("className", "hello2").get("className"));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 3.方法调用
//Instance methods on的参数是一个对象
//Static methods on的参数是一个类
// Instance methods
//value0 = "12";
final String value0 = Reflect.on((Object) "1234").call("substring", 0, 2).get();
// Static methods
//value1 = "true";
final String value1 = Reflect.on(String.class).call("valueOf", true).get();
// 使用joor执行方法
on(abc1).call("soutA");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 4.属性操作
public static class TestField {
private static final int SF_INT1 = new Integer(0);
private static final Integer SF_INT2 = new Integer(0);
private final int F_INT1 = new Integer(0);
private final Integer F_INT2 = new Integer(0);
private TestField I_DATA;
}
//Instant fields,on的参数是一个对象
//Static fields,on的参数是一个类
// Instance fields
// ----------------
TestField testField = new TestField();
/**
* 修改final属性
*/
final Integer value0 = Reflect.on(testField).set("F_INT2", 1).get("F_INT2"); //value0 = 1;
/**
* 获取属性值
*/
final int value1 = Reflect.on(testField).field("F_INT2").get(); //value1 = 1;
/**
* 链式修改多个属性值
*/
Reflect.on(testField).set("F_INT1", 2).set("F_INT2", 2);
/**
* 复杂链式修改多个属性值
*/
Reflect.on(testField).set("I_DATA", Reflect.on(TestField.class).create())
.field("I_DATA").set("F_INT1", 3).set("F_INT2", 3);
// Static fields
// ----------------
/**
* 修改static final属性
*/
final int value2 = Reflect.on(TestField.class).set("SF_INT1", 4).get("SF_INT1"); //value2 = 4;
/**
* 获取静态属性值
*/
final int value3 = Reflect.on(TestField.class).field("SF_INT1").get(); //value3 = 4;
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
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
# 5.抽象代理
public interface StringProxy {
String substring(int beginIndex);
}
String substring = on("java.lang.String")
.create("Hello World")
.as(StringProxy.class) // 为包装类建立一个代理
.substring(6); // 访问代理方法
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 6.原生方法
// 使用原生反射赋值
Class<?> aClass = Class.forName("com.example.entity.ABC");
ABC instance = (ABC) aClass.newInstance();
Field a = aClass.getDeclaredField("A");
Field b = aClass.getDeclaredField("B");
a.setAccessible(true);
a.set(instance,"123");
b.set(instance,"321");
System.out.println(instance);
// 使用原生发射执行方法
Method soutA = aClass.getDeclaredMethod("soutA", null);
soutA.invoke(instance,null);
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12