设为首页 加入收藏

TOP

MyBatis 解析 XML 标签及占位符相关源码剖析(三)
2018-04-08 08:51:29 】 浏览:803
Tags:MyBatis 解析 XML 标签 占位 相关 源码 剖析
ey.update(value); } } if (configuration.getEnvironment() != null) { // issue #176 cacheKey.update(configuration.getEnvironment().getId()); } return cacheKey; }
  1. MetaObject metaObject = configuration.newMetaObject(parameterObject);

这一步是为了获取MetaObject对象,该对象用于根据object类型来包装object对象,以便后续根据#{propertyName}表达式来获取值。其中包括递归查找对象属性的过程。

public MetaObject newMetaObject(Object object) {
  return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
}
public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
  // 防止后续传入空对象,空对象特殊处理
  if (object == null) {
    return SystemMetaObject.NULL_META_OBJECT;
  } else {
    // 第三步
    return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
  }
}
  1. new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);

这一步生成MetaObject对象,内部根据object的具体类型,分别生成不同的objectWrapper对象。

private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
  this.originalObject = object;
  this.objectFactory = objectFactory;
  this.objectWrapperFactory = objectWrapperFactory;
  this.reflectorFactory = reflectorFactory;

  if (object instanceof ObjectWrapper) {
    // 已经是ObjectWrapper对象,则直接返回
    this.objectWrapper = (ObjectWrapper) object;
  } else if (objectWrapperFactory.hasWrapperFor(object)) {
    // 工厂获取obejctWrapper
    this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
  } else if (object instanceof Map) {
    // Map类型的Wrapper,主要用户根据name从map中获取值的封装,具体看源码
    this.objectWrapper = new MapWrapper(this, (Map) object);
  } else if (object instanceof Collection) {
    // collection类的包装器,关于此还有个注意点,参考后记3
    this.objectWrapper = new CollectionWrapper(this, (Collection) object);
  } else if (object.getClass().isArray()) {
    // 数组类型的包装器,这个处理逻辑是发现了一个bug后我自己加的,后面说。
    this.objectWrapper = new ArrayWrapper(this, object);
  } else {
    // 原始bean的包装器,主要通过反射获取属性,以及递归获取属性。
    this.objectWrapper = new BeanWrapper(this, object);
  }
}
  1. value = metaObject.getValue(propertyName);

这一步真正获取了#{propertyName}所代表的值

public Object getValue(String name) {
  // 把propertyName进行Tokenizer化,最简单的例子是用.分割的name,处理为格式化的多级property类型。
  PropertyTokenizer prop = new PropertyTokenizer(name);
  if (prop.hasNext()) {
    // 如果有子级的property即bean.property后面的property,即进入下面的递归过程
    MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
    if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
      return null;
    } else {
      // 开始递归
      return metaValue.getValue(prop.getChildren());
    }
  } else {
    // 第五步:递归终止,直接获取属性。
    return objectWrapper.get(prop);
  }
}
public MetaObject metaObjectForProperty(String name) {
  Object value = getValue(name);
  return MetaObject.forObject(value, objectFactory, objectWrapperFactory, reflectorFactory);
}
  1. objectWrapper.get(prop);

通过第三步中生成的objectWrapper来获取真正的属性值,不同wrapper获取方式不同,以beanWrapper为例:

public Object get(PropertyTokenizer prop) {
  if (prop.getIndex() != null) {
    // 如果有索引即bean[i].property中的[i]时,则尝试解析为collection并取对应的索引值
    Object collection = resolveCollection(prop, object);
    return getCollectionValue(prop, col
首页 上一页 1 2 3 4 5 下一页 尾页 3/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Java日志框架:logback详解 下一篇一次非典型性 Redis 阻塞总结

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目