# 一.joor 简单介绍

# 1.功能介绍

  1. 提供 on()操作符对类名、Class、Object 进行统一实例化为 Reflect 对象,后续所有的反射操作基于该 Reflect 对象。
  2. 有功能调用方式均被封装成返回 Reflect 对象的链式结构,在使用上使得代码更加简洁。
  3. 对方法的签名匹配封装了更完善的匹配规则,包括精确匹配 exactMethod()、近似匹配 similarMethod()【对函数参数的近似匹配(int -> Integer)】和基类搜索等。
  4. 调用私有方法的不需要显示调用 setAccessible(),内部动态读取 public 标记自动适配。
  5. 更加简洁的实现了对象构造函数的反射调用 create()方法。
  6. 函数的调用 call()方法组合成了可以拼接在 Reflect 的对象后面的链式方法。
  7. 额外增加了高级操作符 as(),它实现了类的代理访问以及 POJO 对象的 get/set/is 方法实现。

# 2.和传统反射优势

从上面的例子就可以看到 jOOR 明显的优势:

  1. 简化了反射冗长的异常处理
  2. 简化了对 Class、Method、Field、Constructor 反射类的实例化,改为统一 Reflect 替换
  3. 支持 private 方法的调用,内部动态区分是否需要 accessible()
  4. 将反射调用封装为更流行的链式调用方式,代码更容易理解(类似 Rxjava 的封装方式)
  5. 支持类型内部 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

# 二.使用

# 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.简单示例

// 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

# 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

# 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

# 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

# 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

# 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
上次更新: 10/29/2024, 10:27:50 AM