reflection包下的invoker子包是执行器子包,该子包中的类是基于反射实现对对象方法的调用和属性的读写。
该包下提供了一个invoker接口及其三个实现类,其类结构图如下:
GetFieldInvoker:负责对象属性的读操作;
SetFieldInvoker:负责对象属性的写操作;
MethodInvoker:负责对象方法的调用
接口Invoker下定义了两个方法:
/**
* target 被代理的目标对象
* args 方法的参数
* Object 方法的返回值
*/
Object invoke(Object target, Object[] args) ;
invoke方法即执行方法,该方法负责完成对象方法的调用和对象属性的读写。
在三个实现类中,分别是属性读取操作、属性赋值操作、方法调用操作。
Class<?> getType();
getType方法用来获取类型。在读写操作中直接返回目标属性的类型;
在方法执行操作中,若目标方法参数有且仅有一个入参则直接返回参数的类型,否则返回方法返回值的类型。
MethodInvoker源码
package org.apache.ibatis.reflection.invoker;
public class MethodInvoker implements Invoker {
private final Class<?> type;
// 被代理对象的方法
private final Method method;
public MethodInvoker(Method method) {
this.method = method;
// 判断被代理对象方法的参数是否仅有一个
if (method.getParameterTypes().length == 1) {
type = method.getParameterTypes()[0];
} else {
type = method.getReturnType();
}
}
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
return method.invoke(target, args);
}
@Override
public Class<?> getType() {
return type;
}
}
测试示例:
package com.xncoding.pos.common.dao.entity;
import lombok.Data;
@Data
public class User {
public Integer age = 10;
public String name = "张三";
public User(){}
public User(String name,Integer age){
this.name = name;
this.age =age;
}
public String selfDesc(){
return "我叫"+this.name+",今年"+this.age+"岁了。";
}
}
package com.xncoding.pos;
import com.xncoding.pos.common.dao.entity.User;
import org.apache.ibatis.reflection.invoker.GetFieldInvoker;
import org.apache.ibatis.reflection.invoker.MethodInvoker;
import org.apache.ibatis.reflection.invoker.SetFieldInvoker;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@SpringBootTest
public class TestMethodGetSetInvoker {
@Test
public void test()throws Exception{
System.out.println("测试属性读操作-----------------------");
this.testGet();
System.out.println("测试属性写操作-----------------------");
this.testSet();
System.out.println("测试方法调用操作-----------------------");
this.testMethod();
}
@Test
public void testGet() throws Exception{
Field[] fields = User.class.getDeclaredFields();
for (Field field : fields) {
GetFieldInvoker fieldInvoker = new GetFieldInvoker(field);
Class<?> fieldType = fieldInvoker.getType();
System.out.println("fieldType:"+fieldType);
Object fieldVal = fieldInvoker.invoke(new User(), null);
System.out.println("fieldVal:"+fieldVal);
}
}
@Test
public void testSet() throws Exception{
Field[] fields = User.class.getDeclaredFields();
User user = new User();
for (Field field : fields) {
SetFieldInvoker fieldInvoker = new SetFieldInvoker(field);
Class<?> fieldType = fieldInvoker.getType();
System.out.println("fieldType:"+fieldType);
if(fieldType.isAssignableFrom(Integer.class)){
fieldInvoker.invoke(user,new Object[]{24});
}
if (fieldType.isAssignableFrom(String.class)){
fieldInvoker.invoke(user,new Object[]{"李四"});
}
}
System.out.println("user:"+user);
}
@Test
public void testMethod() throws Exception{
Method method = User.class.getMethod("selfDesc", null);
MethodInvoker methodInvoker = new MethodInvoker(method);
Class<?> type = methodInvoker.getType();
System.out.println("type:"+type);
Object methodVal = methodInvoker.invoke(new User(), null);
System.out.println("methodVal:"+methodVal);
}
}
输出结果:
注意这里其实使用到了装饰器模式,GetFieldInvoker、SetFieldInvoker、MethodInvoker都是通过有参构造将传入的对象包装成相应的操作对象。