Mybatis工作机制源码分析—初始化—mapper配置文件解析

      本文以源码分析的形式讲解Mybatis是如何进行mapper配置文件的解析工作的。

时序图


相关源码

/** XMLMapperBuilder.java */
// 构造XMLMapperBuilder
public XMLMapperBuilder(InputStream inputStream, Configuration configuration, String resource, Map<String, XNode> sqlFragments) {
	this(new XPathParser(inputStream, true, configuration.getVariables(), new XMLMapperEntityResolver()),
		configuration, resource, sqlFragments);
}

private XMLMapperBuilder(XPathParser parser, Configuration configuration, String resource, Map<String, XNode> sqlFragments) {
	super(configuration);
	this.builderAssistant = new MapperBuilderAssistant(configuration, resource);
	this.parser = parser;
	this.sqlFragments = sqlFragments;
	this.resource = resource;
}

// MyBatis mapper配置文件解析
public void parse() {
	if (!configuration.isResourceLoaded(resource)) {
	  // parser.evalNode("/mapper"):获取Mybatis mapper配置文件的根节点XNode
	  configurationElement(parser.evalNode("/mapper"));
	  // resource添加到loadedResources
	  configuration.addLoadedResource(resource);
	  bindMapperForNamespace();
	}

	parsePendingResultMaps();
	parsePendingChacheRefs();
	parsePendingStatements();
}

private void configurationElement(XNode context) {
	try {
	  // 获取<mapper>的"namespace"属性
	  String namespace = context.getStringAttribute("namespace");
	  if (namespace == null || namespace.equals("")) {
		throw new BuilderException("Mapper's namespace cannot be empty");
	  }
	  // builderAssistant设置currentNamespace
	  builderAssistant.setCurrentNamespace(namespace);
	  // 解析"mapper\cache-ref"元素
	  cacheRefElement(context.evalNode("cache-ref"));
	  // 解析"mapper\cache"元素
	  cacheElement(context.evalNode("cache"));
	  // 解析"/mapper/parameterMap"元素
	  parameterMapElement(context.evalNodes("/mapper/parameterMap"));
	  // 解析"/mapper/resultMap"元素
	  resultMapElements(context.evalNodes("/mapper/resultMap"));
	  // 解析"/mapper/sql"元素
	  sqlElement(context.evalNodes("/mapper/sql"));
	  // 解析"/mapper/select|insert|update|delete"元素
	  buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
	} catch (Exception e) {
	  throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e);
	}
}

详细流程
解析"mapper\cache-ref"元素

private void cacheRefElement(XNode context) {
	if (context != null) {
	  // configuration cacheRefMap添加缓存引用键值对
	  configuration.addCacheRef(builderAssistant.getCurrentNamespace(), context.getStringAttribute("namespace"));
	  CacheRefResolver cacheRefResolver = new CacheRefResolver(builderAssistant, context.getStringAttribute("namespace"));
	  try {
		// 设置MapperBuilderAssistant的currentCache为"namespace"引用的缓存
		cacheRefResolver.resolveCacheRef();
	  } catch (IncompleteElementException e) {
		configuration.addIncompleteCacheRef(cacheRefResolver);
	  }
	}
}

/** Configuration.java */
public void addCacheRef(String namespace, String referencedNamespace) {
	cacheRefMap.put(namespace, referencedNamespace);
}

/** CacheRefResolver.java */
public CacheRefResolver(MapperBuilderAssistant assistant, String cacheRefNamespace) {
	this.assistant = assistant;
	this.cacheRefNamespace = cacheRefNamespace;
}

public Cache resolveCacheRef() {
	return assistant.useCacheRef(cacheRefNamespace);
}

/** MapperBuilderAssistant.java */
// 设置MapperBuilderAssistant的currentCache为namespace对应的缓存
public Cache useCacheRef(String namespace) {
	if (namespace == null) {
	  throw new BuilderException("cache-ref element requires a namespace attribute.");
	}
	try {
	  unresolvedCacheRef = true;
	  Cache cache = configuration.getCache(namespace);
	  if (cache == null) {
		throw new IncompleteElementException("No cache for namespace '" + namespace + "' could be found.");
	  }
	  currentCache = cache;
	  unresolvedCacheRef = false;
	  return cache;
	} catch (IllegalArgumentException e) {
	  throw new IncompleteElementException("No cache for namespace '" + namespace + "' could be found.", e);
	}
}

解析"mapper\cache"元素

/** XMLMapperBuilder.java */
private void cacheElement(XNode context) throws Exception {
	if (context != null) {
	  // 获取<cache>的"type"属性,默认为PerpetualCache
	  String type = context.getStringAttribute("type", "PERPETUAL");
	  Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
	  // 获取<cache>的"eviction"属性,默认为LruCache
	  String eviction = context.getStringAttribute("eviction", "LRU");
	  Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);
	  // 获取<cache>的"flushInterval"属性,缓存刷新间隔时间
	  Long flushInterval = context.getLongAttribute("flushInterval");
	  // 获取<cache>的"size"属性,缓存引用的最大数
	  Integer size = context.getIntAttribute("size");
	  // 获取<cache>的"readOnly"属性,默认为false
	  boolean readWrite = !context.getBooleanAttribute("readOnly", false);
	  // 获取<cache>的"blocking"属性,默认为false
	  boolean blocking = context.getBooleanAttribute("blocking", false);
	  Properties props = context.getChildrenAsProperties();
	  builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);
	}
}

/** MapperBuilderAssistant.java */
public Cache useNewCache(Class<? extends Cache> typeClass,
  Class<? extends Cache> evictionClass,
  Long flushInterval,
  Integer size,
  boolean readWrite,
  boolean blocking,
  Properties props) {
	typeClass = valueOrDefault(typeClass, PerpetualCache.class);
	evictionClass = valueOrDefault(evictionClass, LruCache.class);
	// 根据相关属性,构建cache
	Cache cache = new CacheBuilder(currentNamespace)
		.implementation(typeClass)
		.addDecorator(evictionClass)
		.clearInterval(flushInterval)
		.size(size)
		.readWrite(readWrite)
		.blocking(blocking)
		.properties(props)
		.build();
	// 添加到configuration caches
	configuration.addCache(cache);
	// 设置为builderAssistant的currentCache
	currentCache = cache;
	return cache;
}

/** CacheBuilder.java */
public Cache build() {
	// 设置CacheBuilder中implementation、decorators相关默认值
	setDefaultImplementations();
	// 创建implementation Cache
	Cache cache = newBaseCacheInstance(implementation, id);
	// 用properties设置cache相关属性
	setCacheProperties(cache);
	// issue #352, do not apply decorators to custom caches
	if (PerpetualCache.class.equals(cache.getClass())) {
	  for (Class<? extends Cache> decorator : decorators) {
		// 用Constructor反射装饰Cache
		cache = newCacheDecoratorInstance(decorator, cache);
		// 重新用properties设置cache相关属性
		setCacheProperties(cache);
	  }
	  cache = setStandardDecorators(cache);
	} else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) {
	  cache = new LoggingCache(cache);
	}
	return cache;
}

private void setDefaultImplementations() {
	if (implementation == null) {
	  implementation = PerpetualCache.class;
	  if (decorators.isEmpty()) {
		decorators.add(LruCache.class);
	  }
	}
}

// 用Constructor反射构建Cache
private Cache newBaseCacheInstance(Class<? extends Cache> cacheClass, String id) {
	Constructor<? extends Cache> cacheConstructor = getBaseCacheConstructor(cacheClass);
	try {
	  return cacheConstructor.newInstance(id);
	} catch (Exception e) {
	  throw new CacheException("Could not instantiate cache implementation (" + cacheClass + "). Cause: " + e, e);
	}
}

// 用反射设置cache相关参数
private void setCacheProperties(Cache cache) {
	if (properties != null) {
	  MetaObject metaCache = SystemMetaObject.forObject(cache);
	  for (Map.Entry<Object, Object> entry : properties.entrySet()) {
		String name = (String) entry.getKey();
		String value = (String) entry.getValue();
		if (metaCache.hasSetter(name)) {
		  Class<?> type = metaCache.getSetterType(name);
		  if (String.class == type) {
			metaCache.setValue(name, value);
		  } else if (int.class == type
			  || Integer.class == type) {
			metaCache.setValue(name, Integer.valueOf(value));
		  } else if (long.class == type
			  || Long.class == type) {
			metaCache.setValue(name, Long.valueOf(value));
		  } else if (short.class == type
			  || Short.class == type) {
			metaCache.setValue(name, Short.valueOf(value));
		  } else if (byte.class == type
			  || Byte.class == type) {
			metaCache.setValue(name, Byte.valueOf(value));
		  } else if (float.class == type
			  || Float.class == type) {
			metaCache.setValue(name, Float.valueOf(value));
		  } else if (boolean.class == type
			  || Boolean.class == type) {
			metaCache.setValue(name, Boolean.valueOf(value));
		  } else if (double.class == type
			  || Double.class == type) {
			metaCache.setValue(name, Double.valueOf(value));
		  } else {
			throw new CacheException("Unsupported property type for cache: '" + name + "' of type " + type);
		  }
		}
	  }
	}
}

// 用Constructor反射装饰Cache
private Cache newCacheDecoratorInstance(Class<? extends Cache> cacheClass, Cache base) {
	Constructor<? extends Cache> cacheConstructor = getCacheDecoratorConstructor(cacheClass);
	try {
	  return cacheConstructor.newInstance(base);
	} catch (Exception e) {
	  throw new CacheException("Could not instantiate cache decorator (" + cacheClass + "). Cause: " + e, e);
	}
}

// 用Standard Decorator装饰cache
private Cache setStandardDecorators(Cache cache) {
	try {
	  // 设置size属性
	  MetaObject metaCache = SystemMetaObject.forObject(cache);
	  if (size != null && metaCache.hasSetter("size")) {
		metaCache.setValue("size", size);
	  }
	  // ScheduledCache装饰cache,设置clearInterval,即缓存clear时间间隔
	  if (clearInterval != null) {
		cache = new ScheduledCache(cache);
		((ScheduledCache) cache).setClearInterval(clearInterval);
	  }
	  // SerializedCache装饰cache,表明cache可序列化读写
	  if (readWrite) {
		cache = new SerializedCache(cache);
	  }
	  // LoggingCache装饰cache,记录缓存命中率(即getObject成功)的日志
	  cache = new LoggingCache(cache);
	  // SynchronizedCache装饰cache,缓存相关操作线程安全,通过在相关方法上加synchronized实现
	  cache = new SynchronizedCache(cache);
	  if (blocking) {
		// BlockingCache装饰cache,缓存相关操作(getObject、putObject)通过获取对应key的lock进行
		cache = new BlockingCache(cache);
	  }
	  return cache;
	} catch (Exception e) {
	  throw new CacheException("Error building standard cache decorators.  Cause: " + e, e);
	}
}

解析"/mapper/parameterMap"元素

/** XMLMapperBuilder.java */
// 解析"/mapper/parameterMap"元素
private void parameterMapElement(List<XNode> list) throws Exception {
	for (XNode parameterMapNode : list) {
	  // 获取id属性
	  String id = parameterMapNode.getStringAttribute("id");
	  // 获取type属性
	  String type = parameterMapNode.getStringAttribute("type");
	  // type属性对应的parameterClass
	  Class<?> parameterClass = resolveClass(type);
	  // 解析"/mapper/parameterMap/parameter"元素列表
	  List<XNode> parameterNodes = parameterMapNode.evalNodes("parameter");
	  List<ParameterMapping> parameterMappings = new ArrayList<ParameterMapping>();
	  for (XNode parameterNode : parameterNodes) {
		// 获取<parameter>的property属性
		String property = parameterNode.getStringAttribute("property");
		// 获取<parameter>的javaType属性
		String javaType = parameterNode.getStringAttribute("javaType");
		// 获取<parameter>的jdbcType属性
		String jdbcType = parameterNode.getStringAttribute("jdbcType");
		// 获取<parameter>的resultMap属性
		String resultMap = parameterNode.getStringAttribute("resultMap");
		// 获取<parameter>的mode属性
		String mode = parameterNode.getStringAttribute("mode");
		// 获取<parameter>的typeHandler属性
		String typeHandler = parameterNode.getStringAttribute("typeHandler");
		// 获取<parameter>的numericScale属性
		Integer numericScale = parameterNode.getIntAttribute("numericScale");
		// 解析参数的模式(ParameterMode.IN, ParameterMode.OUT, ParameterMode.INOUT)
		ParameterMode modeEnum = resolveParameterMode(mode);
		// 解析javaType对应的Class
		Class<?> javaTypeClass = resolveClass(javaType);
		// 解析jdbcType对应的JdbcType类型
		JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
		// 解析typeHandler对应的Class类型
		@SuppressWarnings("unchecked")
		Class<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) resolveClass(typeHandler);
		// 构建ParameterMapping
		ParameterMapping parameterMapping = builderAssistant.buildParameterMapping(parameterClass, property, javaTypeClass, jdbcTypeEnum, resultMap, modeEnum, typeHandlerClass, numericScale);
		parameterMappings.add(parameterMapping);
	  }
	  // configuration添加parameterMap
	  builderAssistant.addParameterMap(id, parameterClass, parameterMappings);
	}
}

/** BaseBuilder.java */
protected ParameterMode resolveParameterMode(String alias) {
	if (alias == null) {
	  return null;
	}
	try {
	  return ParameterMode.valueOf(alias);
	} catch (IllegalArgumentException e) {
	  throw new BuilderException("Error resolving ParameterMode. Cause: " + e, e);
	}
}

protected JdbcType resolveJdbcType(String alias) {
	if (alias == null) {
	  return null;
	}
	try {
	  return JdbcType.valueOf(alias);
	} catch (IllegalArgumentException e) {
	  throw new BuilderException("Error resolving JdbcType. Cause: " + e, e);
	}
}

protected Class<?> resolveClass(String alias) {
	if (alias == null) {
	  return null;
	}
	try {
	  return resolveAlias(alias);
	} catch (Exception e) {
	  throw new BuilderException("Error resolving class. Cause: " + e, e);
	}
}

/** MapperBuilderAssistant.java */
// 构建ParameterMapping
public ParameterMapping buildParameterMapping(
  Class<?> parameterType,
  String property,
  Class<?> javaType,
  JdbcType jdbcType,
  String resultMap,
  ParameterMode parameterMode,
  Class<? extends TypeHandler<?>> typeHandler,
  Integer numericScale) {
	// 带上currentNamespace前缀
	resultMap = applyCurrentNamespace(resultMap, true);

	// Class parameterType = parameterMapBuilder.type();
	// 确定javaTypeClass
	Class<?> javaTypeClass = resolveParameterJavaType(parameterType, property, javaType, jdbcType);
	// 获取TypeHandler实例
	TypeHandler<?> typeHandlerInstance = resolveTypeHandler(javaTypeClass, typeHandler);

	// 构建ParameterMapping
	ParameterMapping.Builder builder = new ParameterMapping.Builder(configuration, property, javaTypeClass);
	builder.jdbcType(jdbcType);
	builder.resultMapId(resultMap);
	builder.mode(parameterMode);
	builder.numericScale(numericScale);
	builder.typeHandler(typeHandlerInstance);
	return builder.build();
}

// 根据resultType、property、javaType、jdbcType确定javaType对应的Class
private Class<?> resolveParameterJavaType(Class<?> resultType, String property, Class<?> javaType, JdbcType jdbcType) {
	if (javaType == null) { // javaType为null
	  if (JdbcType.CURSOR.equals(jdbcType)) {
		// jdbcType为JdbcType.CURSOR,则javaType为java.sql.ResultSet.class
		javaType = java.sql.ResultSet.class;
	  } else if (Map.class.isAssignableFrom(resultType)) {
		// resultType为Map系列,javaType为Object.class
		javaType = Object.class;
	  } else {
		// 用resultType、property反射获取javaType对应的Class
		MetaClass metaResultType = MetaClass.forClass(resultType, configuration.getReflectorFactory());
		javaType = metaResultType.getGetterType(property);
	  }
	}
	if (javaType == null) {
	  javaType = Object.class;
	}
	return javaType;
}

/** BaseBuilder.java */
// 根据javaType、typeHandlerType获取TypeHandler实例
protected TypeHandler<?> resolveTypeHandler(Class<?> javaType, Class<? extends TypeHandler<?>> typeHandlerType) {
	if (typeHandlerType == null) {
	  return null;
	}
	// javaType ignored for injected handlers see issue #746 for full detail
	TypeHandler<?> handler = typeHandlerRegistry.getMappingTypeHandler(typeHandlerType);
	if (handler == null) {
	  // not in registry, create a new one
	  handler = typeHandlerRegistry.getInstance(javaType, typeHandlerType);
	}
	return handler;
}

/** MapperBuilderAssistant.java */
public ParameterMap addParameterMap(String id, Class<?> parameterClass, List<ParameterMapping> parameterMappings) {
	// 带上currentNamespace前缀
	id = applyCurrentNamespace(id, false);
	// 构建ParameterMap
	ParameterMap.Builder parameterMapBuilder = new ParameterMap.Builder(configuration, id, parameterClass, parameterMappings);
	ParameterMap parameterMap = parameterMapBuilder.build();
	// configuration添加parameterMap
	configuration.addParameterMap(parameterMap);
	return parameterMap;
}

解析"/mapper/resultMap"元素

/** XMLMapperBuilder.java */
// 解析"/mapper/resultMap"元素
private void resultMapElements(List<XNode> list) throws Exception {
	for (XNode resultMapNode : list) {
	  try {
		resultMapElement(resultMapNode);
	  } catch (IncompleteElementException e) {
		// ignore, it will be retried
	  }
	}
}

private ResultMap resultMapElement(XNode resultMapNode) throws Exception {
	return resultMapElement(resultMapNode, Collections.<ResultMapping> emptyList());
}

private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings) throws Exception {
ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier());
	// 获取<resultMap>的"id"属性
	String id = resultMapNode.getStringAttribute("id",
		resultMapNode.getValueBasedIdentifier());
	// 获取<resultMap>的"type"属性
	String type = resultMapNode.getStringAttribute("type",
		resultMapNode.getStringAttribute("ofType",
			resultMapNode.getStringAttribute("resultType",
				resultMapNode.getStringAttribute("javaType"))));
	// 获取<resultMap>的"extends"属性
	String extend = resultMapNode.getStringAttribute("extends");
	// 获取<resultMap>的"autoMapping"属性
	Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
	Class<?> typeClass = resolveClass(type);
	Discriminator discriminator = null;
	List<ResultMapping> resultMappings = new ArrayList<ResultMapping>();
	resultMappings.addAll(additionalResultMappings);
	List<XNode> resultChildren = resultMapNode.getChildren();
	for (XNode resultChild : resultChildren) {
	  if ("constructor".equals(resultChild.getName())) {
		// 处理"/mapper/resultMap/constructor"元素
		processConstructorElement(resultChild, typeClass, resultMappings);
	  } else if ("discriminator".equals(resultChild.getName())) {
		// 处理"/mapper/resultMap/discriminator"元素
		discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings);
	  } else {
		// 处理"/mapper/resultMap/id"元素
		List<ResultFlag> flags = new ArrayList<ResultFlag>();
		if ("id".equals(resultChild.getName())) {
		  flags.add(ResultFlag.ID);
		}
		resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));
	  }
	}
	ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping);
	try {
	  // 解析为ResultMap
	  return resultMapResolver.resolve();
	} catch (IncompleteElementException  e) {
	  configuration.addIncompleteResultMap(resultMapResolver);
	  throw e;
	}
}

private void processConstructorElement(XNode resultChild, Class<?> resultType, List<ResultMapping> resultMappings) throws Exception {
	List<XNode> argChildren = resultChild.getChildren();
	for (XNode argChild : argChildren) {
	  List<ResultFlag> flags = new ArrayList<ResultFlag>();
	  flags.add(ResultFlag.CONSTRUCTOR);
	  if ("idArg".equals(argChild.getName())) {
		flags.add(ResultFlag.ID);
	  }
	  resultMappings.add(buildResultMappingFromContext(argChild, resultType, flags));
	}
}

private ResultMapping buildResultMappingFromContext(XNode context, Class<?> resultType, List<ResultFlag> flags) throws Exception {
	// 获取相关属性
	String property = context.getStringAttribute("property");
	String column = context.getStringAttribute("column");
	String javaType = context.getStringAttribute("javaType");
	String jdbcType = context.getStringAttribute("jdbcType");
	String nestedSelect = context.getStringAttribute("select");
	String nestedResultMap = context.getStringAttribute("resultMap",
		processNestedResultMappings(context, Collections.<ResultMapping> emptyList()));
	String notNullColumn = context.getStringAttribute("notNullColumn");
	String columnPrefix = context.getStringAttribute("columnPrefix");
	String typeHandler = context.getStringAttribute("typeHandler");
	String resulSet = context.getStringAttribute("resultSet");
	String foreignColumn = context.getStringAttribute("foreignColumn");
	boolean lazy = "lazy".equals(context.getStringAttribute("fetchType", configuration.isLazyLoadingEnabled() ? "lazy" : "eager"));
	Class<?> javaTypeClass = resolveClass(javaType);
	@SuppressWarnings("unchecked")
	Class<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) resolveClass(typeHandler);
	JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
	return builderAssistant.buildResultMapping(resultType, property, column, javaTypeClass, jdbcTypeEnum, nestedSelect, nestedResultMap, notNullColumn, columnPrefix, typeHandlerClass, flags, resulSet, foreignColumn, lazy);
}

/** MapperBuilderAssistant.java */
// 构建ResultMapping
public ResultMapping buildResultMapping(
  Class<?> resultType,
  String property,
  String column,
  Class<?> javaType,
  JdbcType jdbcType,
  String nestedSelect,
  String nestedResultMap,
  String notNullColumn,
  String columnPrefix,
  Class<? extends TypeHandler<?>> typeHandler,
  List<ResultFlag> flags,
  String resultSet,
  String foreignColumn,
  boolean lazy) {
	Class<?> javaTypeClass = resolveResultJavaType(resultType, property, javaType);
	TypeHandler<?> typeHandlerInstance = resolveTypeHandler(javaTypeClass, typeHandler);
	List<ResultMapping> composites = parseCompositeColumnName(column);
	if (composites.size() > 0) {
	  column = null;
	}
	ResultMapping.Builder builder = new ResultMapping.Builder(configuration, property, column, javaTypeClass);
	builder.jdbcType(jdbcType);
	builder.nestedQueryId(applyCurrentNamespace(nestedSelect, true));
	builder.nestedResultMapId(applyCurrentNamespace(nestedResultMap, true));
	builder.resultSet(resultSet);
	builder.typeHandler(typeHandlerInstance);
	builder.flags(flags == null ? new ArrayList<ResultFlag>() : flags);
	builder.composites(composites);
	builder.notNullColumns(parseMultipleColumnNames(notNullColumn));
	builder.columnPrefix(columnPrefix);
	builder.foreignColumn(foreignColumn);
	builder.lazy(lazy);
	return builder.build();
}

/** XMLMapperBuilder.java */
private Discriminator processDiscriminatorElement(XNode context, Class<?> resultType, List<ResultMapping> resultMappings) throws Exception {
	String column = context.getStringAttribute("column");
	String javaType = context.getStringAttribute("javaType");
	String jdbcType = context.getStringAttribute("jdbcType");
	String typeHandler = context.getStringAttribute("typeHandler");
	Class<?> javaTypeClass = resolveClass(javaType);
	@SuppressWarnings("unchecked")
	Class<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) resolveClass(typeHandler);
	JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
	Map<String, String> discriminatorMap = new HashMap<String, String>();
	// 获取discriminatorMap
	for (XNode caseChild : context.getChildren()) {
	  String value = caseChild.getStringAttribute("value");
	  String resultMap = caseChild.getStringAttribute("resultMap", processNestedResultMappings(caseChild, resultMappings));
	  discriminatorMap.put(value, resultMap);
	}
	// 构建Discriminator
	return builderAssistant.buildDiscriminator(resultType, column, javaTypeClass, jdbcTypeEnum, typeHandlerClass, discriminatorMap);
}

/** MapperBuilderAssistant.java */
public Discriminator buildDiscriminator(
  Class<?> resultType,
  String column,
  Class<?> javaType,
  JdbcType jdbcType,
  Class<? extends TypeHandler<?>> typeHandler,
  Map<String, String> discriminatorMap) {
	// 构建resultMapping
	ResultMapping resultMapping = buildResultMapping(
		resultType,
		null,
		column,
		javaType,
		jdbcType,
		null,
		null,
		null,
		null,
		typeHandler,
		new ArrayList<ResultFlag>(),
		null,
		null,
		false);
	// discriminatorMap带上namespace
	Map<String, String> namespaceDiscriminatorMap = new HashMap<String, String>();
	for (Map.Entry<String, String> e : discriminatorMap.entrySet()) {
	  String resultMap = e.getValue();
	  resultMap = applyCurrentNamespace(resultMap, true);
	  namespaceDiscriminatorMap.put(e.getKey(), resultMap);
	}
	// 构建Discriminator
	Discriminator.Builder discriminatorBuilder = new Discriminator.Builder(configuration, resultMapping, namespaceDiscriminatorMap);
	return discriminatorBuilder.build();
}

/** ResultMapResolver.java */
// 解析ResultMap
public ResultMap resolve() {
	return assistant.addResultMap(this.id, this.type, this.extend, this.discriminator, this.resultMappings, this.autoMapping);
}

/** MapperBuilderAssistant.java */
public ResultMap addResultMap(
  String id,
  Class<?> type,
  String extend,
  Discriminator discriminator,
  List<ResultMapping> resultMappings,
  Boolean autoMapping) {
	id = applyCurrentNamespace(id, false);
	extend = applyCurrentNamespace(extend, true);

	ResultMap.Builder resultMapBuilder = new ResultMap.Builder(configuration, id, type, resultMappings, autoMapping);
	if (extend != null) {
	  // 整合extend ResultMap
	  if (!configuration.hasResultMap(extend)) {
		throw new IncompleteElementException("Could not find a parent resultmap with id '" + extend + "'");
	  }
	  ResultMap resultMap = configuration.getResultMap(extend);
	  List<ResultMapping> extendedResultMappings = new ArrayList<ResultMapping>(resultMap.getResultMappings());
	  // 删除重复的ResultMapping
	  extendedResultMappings.removeAll(resultMappings);
	  // Remove parent constructor if this resultMap declares a constructor.
	  boolean declaresConstructor = false;
	  for (ResultMapping resultMapping : resultMappings) {
		if (resultMapping.getFlags().contains(ResultFlag.CONSTRUCTOR)) {
		  declaresConstructor = true;
		  break;
		}
	  }
	  if (declaresConstructor) {
		Iterator<ResultMapping> extendedResultMappingsIter = extendedResultMappings.iterator();
		while (extendedResultMappingsIter.hasNext()) {
		  if (extendedResultMappingsIter.next().getFlags().contains(ResultFlag.CONSTRUCTOR)) {
			extendedResultMappingsIter.remove();
		  }
		}
	  }
	  resultMappings.addAll(extendedResultMappings);
	}
	resultMapBuilder.discriminator(discriminator);
	// 构建ResultMap
	ResultMap resultMap = resultMapBuilder.build();
	// 添加到configuration
	configuration.addResultMap(resultMap);
	return resultMap;
}

解析"/mapper/sql"元素

/** XMLMapperBuilder.java */
private void sqlElement(List<XNode> list) throws Exception {
	if (configuration.getDatabaseId() != null) {
	  sqlElement(list, configuration.getDatabaseId());
	}
	sqlElement(list, null);
}

private void sqlElement(List<XNode> list, String requiredDatabaseId) throws Exception {
	for (XNode context : list) {
	  String databaseId = context.getStringAttribute("databaseId");
	  String id = context.getStringAttribute("id");
	  id = builderAssistant.applyCurrentNamespace(id, false);
	  if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) {
		// configuration的databaseId匹配context的databaseId
		// 添加到sqlFragments
		sqlFragments.put(id, context);
	  }
	}
}

解析"/mapper/select|insert|update|delete"元素

/** XMLMapperBuilder.java */
private void buildStatementFromContext(List<XNode> list) {
	if (configuration.getDatabaseId() != null) {
	  buildStatementFromContext(list, configuration.getDatabaseId());
	}
	buildStatementFromContext(list, null);
}

private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) {
	for (XNode context : list) {
	  final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId);
	  try {
		statementParser.parseStatementNode();
	  } catch (IncompleteElementException e) {
		configuration.addIncompleteStatement(statementParser);
	  }
	}
}

/** XMLStatementBuilder.java */
// 解析MappedStatement
public void parseStatementNode() {
	String id = context.getStringAttribute("id");
	String databaseId = context.getStringAttribute("databaseId");

	if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {
	  return;
	}

	Integer fetchSize = context.getIntAttribute("fetchSize");
	Integer timeout = context.getIntAttribute("timeout");
	String parameterMap = context.getStringAttribute("parameterMap");
	String parameterType = context.getStringAttribute("parameterType");
	Class<?> parameterTypeClass = resolveClass(parameterType);
	String resultMap = context.getStringAttribute("resultMap");
	String resultType = context.getStringAttribute("resultType");
	String lang = context.getStringAttribute("lang");
	// 获取LanguageDriver实例
	LanguageDriver langDriver = getLanguageDriver(lang);

	Class<?> resultTypeClass = resolveClass(resultType);
	String resultSetType = context.getStringAttribute("resultSetType");
	StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString()));
	ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType);

	String nodeName = context.getNode().getNodeName();
	SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));

	// 默认:对于Select语句,flushCache为false,useCache为true,即读取缓存且不clear;非Select语句则相反
	boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
	boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);
	boolean useCache = context.getBooleanAttribute("useCache", isSelect);

	boolean resultOrdered = context.getBooleanAttribute("resultOrdered", false);

	// Include Fragments before parsing
	XMLIncludeTransformer includeParser = new XMLIncludeTransformer(configuration, builderAssistant);
	includeParser.applyIncludes(context.getNode());

	// Parse selectKey after includes and remove them.
	processSelectKeyNodes(id, parameterTypeClass, langDriver);

	// Parse the SQL (pre: <selectKey> and <include> were parsed and removed)
	SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);
	String resultSets = context.getStringAttribute("resultSets");
	String keyProperty = context.getStringAttribute("keyProperty");
	String keyColumn = context.getStringAttribute("keyColumn");
	KeyGenerator keyGenerator;
	String keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX;
	keyStatementId = builderAssistant.applyCurrentNamespace(keyStatementId, true);
	if (configuration.hasKeyGenerator(keyStatementId)) {
	  keyGenerator = configuration.getKeyGenerator(keyStatementId);
	} else {
	  // 生成keyGenerator
	  keyGenerator = context.getBooleanAttribute("useGeneratedKeys",
		  configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType))
		  ? new Jdbc3KeyGenerator() : new NoKeyGenerator();
	}

	// 构建MappedStatement
	builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
		fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
		resultSetTypeEnum, flushCache, useCache, resultOrdered, 
		keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
}

private LanguageDriver getLanguageDriver(String lang) {
	Class<?> langClass = null;
	if (lang != null) {
	  langClass = resolveClass(lang);
	}
	return builderAssistant.getLanguageDriver(langClass);
}

/** MapperBuilderAssistant.java */
public LanguageDriver getLanguageDriver(Class<?> langClass) {
	if (langClass != null) {
	  configuration.getLanguageRegistry().register(langClass);
	} else {
	  // 获取默认的driverClass:class org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
	  langClass = configuration.getLanguageRegistry().getDefaultDriverClass();
	}
	// 返回LanguageDriver实例
	return configuration.getLanguageRegistry().getDriver(langClass);
}

/** XMLLanguageDriver.java */
public SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) {
	XMLScriptBuilder builder = new XMLScriptBuilder(configuration, script, parameterType);
	return builder.parseScriptNode();
}

/** XMLScriptBuilder.java */
public SqlSource parseScriptNode() {
	// 获取sql语句
	List<SqlNode> contents = parseDynamicTags(context);
	MixedSqlNode rootSqlNode = new MixedSqlNode(contents);
	SqlSource sqlSource = null;
	if (isDynamic) {
	  sqlSource = new DynamicSqlSource(configuration, rootSqlNode);
	} else {
	  // 包装为RawSqlSource
	  sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);
	}
	return sqlSource;
}

List<SqlNode> parseDynamicTags(XNode node) {
	List<SqlNode> contents = new ArrayList<SqlNode>();
	NodeList children = node.getNode().getChildNodes();
	for (int i = 0; i < children.getLength(); i++) {
	  XNode child = node.newXNode(children.item(i));
	  // Node.TEXT_NODE表明为sql语句
	  if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) {
		// 获取源sql语句
		String data = child.getStringBody("");
		// 将源sql语句包装为TextSqlNode
		TextSqlNode textSqlNode = new TextSqlNode(data);
		if (textSqlNode.isDynamic()) { // 检测源sql语句是否包含"${...}"动态表达式
		  contents.add(textSqlNode);
		  isDynamic = true;
		} else {
		  // 直接将源sql语句包装为StaticTextSqlNode
		  contents.add(new StaticTextSqlNode(data));
		}
	  } else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628
		String nodeName = child.getNode().getNodeName();
		NodeHandler handler = nodeHandlers(nodeName);
		if (handler == null) {
		  throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement.");
		}
		handler.handleNode(child, contents);
		isDynamic = true;
	  }
	}
	return contents;
}

/** RawSqlSource.java */
public RawSqlSource(Configuration configuration, SqlNode rootSqlNode, Class<?> parameterType) {
	this(configuration, getSql(configuration, rootSqlNode), parameterType);
}

public RawSqlSource(Configuration configuration, String sql, Class<?> parameterType) {
	SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
	Class<?> clazz = parameterType == null ? Object.class : parameterType;
	sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap<String, Object>());
}

// 获取rootSqlNode中的sql语句
private static String getSql(Configuration configuration, SqlNode rootSqlNode) {
	DynamicContext context = new DynamicContext(configuration, null);
	// 用sqlBuilder组件sql语句
	rootSqlNode.apply(context);
	// 获取sql语句
	return context.getSql();
}

/** MixedSqlNode.java */
public boolean apply(DynamicContext context) {
	for (SqlNode sqlNode : contents) {
	  sqlNode.apply(context);
	}
	return true;
}

/** StaticTextSqlNode.java */
public boolean apply(DynamicContext context) {
	context.appendSql(text);
	return true;
}

/** DynamicContext.java */
public void appendSql(String sql) {
	sqlBuilder.append(sql);
	sqlBuilder.append(" ");
}

public String getSql() {
	return sqlBuilder.toString().trim();
}

/** SqlSourceBuilder.java */
public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
	ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);
	GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
	// 用"?"代替originalSql中的"#{...}"表达式
	String sql = parser.parse(originalSql);
	// 解析为StaticSqlSource
	return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
}

public MappedStatement addMappedStatement(
  String id,
  SqlSource sqlSource,
  StatementType statementType,
  SqlCommandType sqlCommandType,
  Integer fetchSize,
  Integer timeout,
  String parameterMap,
  Class<?> parameterType,
  String resultMap,
  Class<?> resultType,
  ResultSetType resultSetType,
  boolean flushCache,
  boolean useCache,
  boolean resultOrdered,
  KeyGenerator keyGenerator,
  String keyProperty,
  String keyColumn,
  String databaseId,
  LanguageDriver lang,
  String resultSets) {

	if (unresolvedCacheRef) {
	  throw new IncompleteElementException("Cache-ref not yet resolved");
	}

	id = applyCurrentNamespace(id, false);
	boolean isSelect = sqlCommandType == SqlCommandType.SELECT;

	// 构建MappedStatement
	MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType);
	statementBuilder.resource(resource);
	statementBuilder.fetchSize(fetchSize);
	statementBuilder.statementType(statementType);
	statementBuilder.keyGenerator(keyGenerator);
	statementBuilder.keyProperty(keyProperty);
	statementBuilder.keyColumn(keyColumn);
	statementBuilder.databaseId(databaseId);
	statementBuilder.lang(lang);
	statementBuilder.resultOrdered(resultOrdered);
	statementBuilder.resulSets(resultSets);
	setStatementTimeout(timeout, statementBuilder);

	setStatementParameterMap(parameterMap, parameterType, statementBuilder);
	setStatementResultMap(resultMap, resultType, resultSetType, statementBuilder);
	setStatementCache(isSelect, flushCache, useCache, currentCache, statementBuilder);

	MappedStatement statement = statementBuilder.build();
	// 添加到configuration
	configuration.addMappedStatement(statement);
	return statement;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值