mybatis源码学习------Invoker接口及其子类

Invoker介绍

Invoker是对getter和setter方法调用的封装,为了简化对属性和字段的操作,Invoker的实现类使用了适配器模式来屏蔽二者的差异,便于上层代码调用。

Invoker及其实现的类图

在这里插入图片描述

代码比较简单,直接看代码和注释即可

public interface Invoker {
 	//执行调用
  	Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;
	
  Class<?> getType();
}

MethodInvoker

public class MethodInvoker implements Invoker {

  private final Class<?> type;
  private final Method method;

  public MethodInvoker(Method method) {
    this.method = method;
	//如果方法的形参列表长度为1,表示当前方法是set方法,故其type为形参的类型
    if (method.getParameterTypes().length == 1) {
      type = method.getParameterTypes()[0];
    } else {
      //形参列表不为1则为get方法,其type为方法返回类型
      type = method.getReturnType();
    }
  }

  @Override
  public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
    try {
        //执行调用,method.invoke(target, args)为被适配的点
      return method.invoke(target, args);
    } catch (IllegalAccessException e) {
      //如果无法访问,则表示当前方法是private修饰的。
      //于是mybaits会查看默认的安全管理器配置文件$JAVA_HOME/jre/lib/security/java.policy中
      //suppressAccessChecks的值,用于判断是否可以使用setAccessible方法进行强制调用
      if (Reflector.canControlMemberAccessible()) {
        method.setAccessible(true);
        return method.invoke(target, args);
      } else {
        throw e;
      }
    }
  }

  @Override
  public Class<?> getType() {
    return type;
  }
}

关于java的安全管理器可以阅读该文章 https://www.cnblogs.com/yiwangzhibujian/p/6207212.html

AmbiguousMethodInvoker

具有二义性的方法调用器,当调用者调用invoke方法时会抛出ReflectionException

public class AmbiguousMethodInvoker extends MethodInvoker {
  private final String exceptionMessage;

  public AmbiguousMethodInvoker(Method method, String exceptionMessage) {
    super(method);
    this.exceptionMessage = exceptionMessage;
  }

  @Override
  public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
    throw new ReflectionException(exceptionMessage);
  }
}

GetFieldInvoker

获取字段值的调用器,用于适配对没有getter方法的字段值的获取

public class GetFieldInvoker implements Invoker {
  private final Field field;

  public GetFieldInvoker(Field field) {
    this.field = field;
  }

  @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;
      }
    }
  }

  @Override
  public Class<?> getType() {
    return field.getType();
  }
}

SetFieldInvoker

设置字段值的调用器,用于适配对没有setter方法的字段值的设置

public class SetFieldInvoker implements Invoker {
  private final Field field;

  public SetFieldInvoker(Field field) {
    this.field = field;
  }

  @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;
  }

  @Override
  public Class<?> getType() {
    return field.getType();
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值