2.4.4.统一反射操作的适配器 Invoker
优质
小牛编辑
133浏览
2023-12-01
# Invoker
Invoker
接口的作用是统一基于反射处理方法/属性的调用方式,他是适配器模式的一种实现。
适配器模式(包装模式)将一个类的接口适配成用户所期待的,是的原本由于接口不兼容而不能一起工作的类可以一起工作。
在Invoker
接口中定义了两个方法,invoke
方法用于执行反射操作,获取响应的操作结果,getType
方法用于获取方法或者属性对应的类型。
/**
* mybatis中定义的用于执行方法或者属性反射操作的类
* <p>
* 作用是统一基于反射处理方法/属性的调用方式
*
* @author Clinton Begin
*/
public interface Invoker {
/**
* 执行反射操作
*
* @param target 方法或者属性执行的目标对象
* @param args 方法或者属性执行时依赖的参数
* @return 方法执行结果
* @throws IllegalAccessException 无访问权限
* @throws InvocationTargetException 反射执行异常
*/
Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;
/**
* 方法或者属性对应的类型
*/
Class<?> getType();
}
在mybatis中Invoker
接口有三种实现形式:
GetFieldInvoker
用于执行读取属性值的反射操作
GetFieldInvoker
对象的构造方法需要传入一个Field
属性:
private final Field field;
public GetFieldInvoker(Field field) {
this.field = field;
}
他的invoke
方法,基于java的反射实现了获取指定属性值的功能:
@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;
}
}
}
getType
方法则返回对应的field
属性的类型:
@Override
public Class<?> getType() {
return field.getType();
}
SetFieldInvoker
用于执行设置属性值的反射操作
SetFieldInvoker
对象的构造方法也需要传入一个Field
属性:
private final Field field;
public SetFieldInvoker(Field field) {
this.field = field;
}
他的invoke
方法,基于java的反射实现了为指定属性设值的功能:
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException {
try {
// 执行反射
field.set(target, args[0]);
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
// 修改权限,再次执行
field.setAccessible(true);
field.set(target, args[0]);
} else {
throw e;
}
}
return null;
}
getType
方法则返回对应的field
属性的类型:
@Override
public Class<?> getType() {
return field.getType();
}
MethodInvoker
用于执行方法的反射操作
他的构造方法需要一个Method
类型的参数,在他的构造方法中,会根据方法有无入参判断方法是getter
方法还是setter
方法,如果是getter
方法则获取方法的返回类型赋给type
属性, 如果是setter
方法则获取方法的入参类型赋给type
属性:
/**
* 如果方法是getter方法,则表示返回值类型
* 如果方法是setter方法,则表示入参类型
*/
private final Class<?> type;
/**
* 方法本身
*/
private final Method method;
public MethodInvoker(Method method) {
this.method = method;
if (method.getParameterTypes().length == 1) {
// 有方法入参,表示是setter方法
type = method.getParameterTypes()[0];
} else {
// 无入参表示是getter方法
type = method.getReturnType();
}
}
他的invoke
方法,基于java的反射完成方法的调用:
@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;
}
}
}
getType
方法则返回在构造方法中赋值的type
属性的值:
@Override
public Class<?> getType() {
return type;
}