ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Mybatis Invoker

2021-05-19 18:30:44  阅读:238  来源: 互联网

标签:Object public field getter Invoker MethodInvoker Mybatis method


Mybatis中的Invoker对反射API中的Field.get () Fielid.get()  Method.invoke()三个方法进行了二次封装,将一些模板式的代码封装了起来,在新的版本中,还加入了安全检查。

其结构如下:

接口定义:

/**
 * @author Clinton Begin
 */
public interface Invoker {
  Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;

  Class<?> getType();
}

接口定义较为简单,我们来看看它的实现类,先看GetFieldInvoker:

/**
 * @author Clinton Begin
 * 对field的get(获取属性值)操作进行增强,增加了强吻(private修饰的属性通过设置setAccessible方法来强行操作)机制
 * 之所以不用getter方法可能是为了强吻,即不提供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();
  }

GetFiledInvoker,乍一看,还以为是操作getter方法,仔细观察发现它操作的是Field,而非 Method。一般我们自己操作Field时,遇到 private修饰的属性就需要强制访问了,GetFiledInvoker帮我们封装了这一步,而且,只有在发生IllegalAccessException 异常时才做强制访问(用private 修饰的field字段被反射操作时,会抛出此异常),这样做的好处是对于一些无需强制访问的Field,就不再需要开启强制访问,例如用public修饰的Field.

另外这里还会去检查权限的问题,如下代码:

Reflector.canControlMemberAccessible()

就是说当你有权限的时候才能去开启强制访问,否则,你没有权限也去开启强制访问,自然也是失败的。

SetFieldInvoker和GetFieldInvoker代码几乎差不多,唯一区别是一个get,一个set,这里不再赘述。

MethodInvoker:

public class MethodInvoker implements Invoker {

  /**
   * 没有调用,还不清楚作用
   * */
  private final Class<?> type;
  private final Method method;

  /**
   * 参数长度是是1时,type=参数的类型
   * 否则,type=return type
   * */
  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 {
    try {
      return method.invoke(target, args);
    } catch (IllegalAccessException e) {
      if (Reflector.canControlMemberAccessible()) {
        method.setAccessible(true);
        return method.invoke(target, args);
      } else {
        throw e;
      }
    }
  }

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

MethodInvoker 代码和GetFileldInvoker代码逻辑差不多,区别是MethodInvoker操作的是MethodInvoker的是Method对象,那么为什么会即提供了MethodInvoker又提供了GetFileldInvoker/SetFieldInvoker呢?我的猜测是当被操作的Bean有getter/setter时,mybatis会通过MethodInvoker来调用getter/setter完成属性的get/set,当被操作Bean的属性没有提供getter/setter时,这里就需要SetFieldInvoker和GetFieldInvoker来完成对field的get/set了,带着这个疑问我们去看一下Reflector源代码:

从setMethods/getMethods的泛型定义可以看出,这两个集合实际保存的是invoker,接着:

从266和275行可以得到两条信息:

1,setMethods/getMethods的key是field name

2,只有当setMethods中不存在该字段名对应的invoker时,才会添加,那么在什么情况下不存在呢?在该field没有getter/setter时。

也就是说,当setMethods|getMethods中没有field name对应methodInvoker时,才会调用 addSetField/addGetField,我们打开其中一个方法:

286行显示add了一个SetFieldInvoker并put到了setMethods中。

AmbiguousMethodInvoker:

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

Ambiguous是有歧义的意思,从字面意思上来猜测,它是一种提高健壮性的设计,当getter/setter的方法签名相同,返回类型却不同时,初始化不会停止,有歧义的getter/setter也不会被丢弃,如果你不调用,相安无事,当你调用的时候,立马抛出异常告诉你,这个方法可能由歧义。

 

标签:Object,public,field,getter,Invoker,MethodInvoker,Mybatis,method
来源: https://blog.csdn.net/seasonsbin/article/details/117037775

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有