设为首页 加入收藏

TOP

MyBatis 解析 XML 标签及占位符相关源码剖析(四)
2018-04-08 08:51:29 】 浏览:805
Tags:MyBatis 解析 XML 标签 占位 相关 源码 剖析
lection); } else { return getBeanProperty(prop, object); } } protected Object resolveCollection(PropertyTokenizer prop, Object object) { if ("".equals(prop.getName())) { return object; } else { return metaObject.getValue(prop.getName()); } } protected Object getCollectionValue(PropertyTokenizer prop, Object collection) { if (collection instanceof Map) { // 如果是map,则直接取"i"对应的value return ((Map) collection).get(prop.getIndex()); } else { // 否则取集合或者数组中的对应值。下面一堆神奇的if else if是为啥,参考后记2 int i = Integer.parseInt(prop.getIndex()); if (collection instanceof List) { return ((List) collection).get(i); } else if (collection instanceof Object[]) { return ((Object[]) collection)[i]; } else if (collection instanceof char[]) { return ((char[]) collection)[i]; } else if (collection instanceof boolean[]) { return ((boolean[]) collection)[i]; } else if (collection instanceof byte[]) { return ((byte[]) collection)[i]; } else if (collection instanceof double[]) { return ((double[]) collection)[i]; } else if (collection instanceof float[]) { return ((float[]) collection)[i]; } else if (collection instanceof int[]) { return ((int[]) collection)[i]; } else if (collection instanceof long[]) { return ((long[]) collection)[i]; } else if (collection instanceof short[]) { return ((short[]) collection)[i]; } else { throw new ReflectionException("The '" + prop.getName() + "' property of " + collection + " is not a List or Array."); } } } private Object getBeanProperty(PropertyTokenizer prop, Object object) { try { // 反射获取getter方法。 Invoker method = metaClass.getGetInvoker(prop.getName()); try { // 执行getter方法获取值 return method.invoke(object, NO_ARGUMENTS); } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } } catch (RuntimeException e) { throw e; } catch (Throwable t) { throw new ReflectionException("Could not get property '" + prop.getName() + "' from " + object.getClass() + ". Cause: " + t.toString(), t); } }

至此,#{propertyName}的解析就完成了。${}则是直接使用的OGNL表达式解析,不详细解析了。

结论

下面回到问题,仔细分析后,得到错误原因:

上面第三步中,生成的ObjectWrapper类型是BeanWrapper,而BeanWrapper中获取属性值length,会调用反射尝试获取getter方法,并执行。对于一个数组类型的对象,当然是不可能有getter方法的(仅指java)。

而在test中的ids.length则没有问题,是因为test中的表达式是使用的OGNL来执行的。参考第一部分的Expressioneva luator。最后的则是执行的第二部分中的代码逻辑,故报错。

解决

解决方法有三种:

  1. 更换#{array.length}为${array.length}即可解决。
  2. 使用<bind />
<bind name="idCount" value="ids.length" />
LIMIT #{idCount}

读者可以尝试去看下bind标签的处理逻辑。 3. 如上面一样,增加ArrayWrapper:

public class ArrayWrapper implements ObjectWrapper {

  private final Object object;

  public ArrayWrapper(MetaObject metaObject, Object object) {
    if (object.getClass().isArray()) {
      this.object = object;
    } else {
      throw new IllegalArgumentException("object must be an array");
    }
  }

  @Override
  public Object get(PropertyTokenizer prop) {
    if ("length".equals(prop.getName())) {
      return Array.getLength(object);
    }
    throw new UnsupportedOperationException();
  }
  ... // 其他未覆盖方法均抛出UnsupportedOperationException异常。
}

这里通过判断属性值为”length”来获取数组长度,其他均抛出异常。这样便支持了#{}占位符中数组长度的获取。

后记

  1. 有意思的注释
if (value.getClass().isArray()) {
  // the array may b
首页 上一页 1 2 3 4 5 下一页 尾页 4/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Java日志框架:logback详解 下一篇一次非典型性 Redis 阻塞总结

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目