private void configurationElement(XNode context) { try { String namespace = context.getStringAttribute("namespace"); if (namespace == null || namespace.equals("")) { throw new BuilderException("Mapper's namespace cannot be empty"); } builderAssistant.setCurrentNamespace(namespace); cacheRefElement(context.evalNode("cache-ref")); //<cache-ref/>标签解析 cacheElement(context.evalNode("cache")); //<cache>标签解析 parameterMapElement(context.evalNodes("/mapper/parameterMap")); //<parameterMap>标签解析 resultMapElements(context.evalNodes("/mapper/resultMap")); //<resultMap>标签解析 sqlElement(context.evalNodes("/mapper/sql")); //<sql>标签解析 buildStatementFromContext(context.evalNodes("select|insert|update|delete")); } catch (Exception e) { throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e); } } //<cache-ref>标签解析 private void cacheRefElement(XNode context) { if (context != null) { //当前命名空间与cache-ref中配置的命名空间增加映射关系 configuration.addCacheRef(builderAssistant.getCurrentNamespace(), context.getStringAttribute("namespace")); CacheRefResolver cacheRefResolver = new CacheRefResolver(builderAssistant, context.getStringAttribute("namespace")); try { cacheRefResolver.resolveCacheRef(); } catch (IncompleteElementException e) { configuration.addIncompleteCacheRef(cacheRefResolver); } } } public Cache resolveCacheRef() { return assistant.useCacheRef(cacheRefNamespace); } //验证cache_ref关联的缓存对象是否存在 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); } } //解析<cache>标签 private void cacheElement(XNode context) throws Exception { if (context != null) { //默认使用PERPETUAL来持久化 String type = context.getStringAttribute("type", "PERPETUAL"); Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type); //缓存回收策略:LRU(最近最少使用) String eviction = context.getStringAttribute("eviction", "LRU"); Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction); //缓存刷新时间间隔配置 Long flushInterval = context.getLongAttribute("flushInterval"); //缓存引用数目配置 Integer size = context.getIntAttribute("size"); //缓存只读属性配置 boolean readWrite = !context.getBooleanAttribute("readOnly", false); //缓存blocking属性配置 boolean blocking = context.getBooleanAttribute("blocking", false); Properties props = context.getChildrenAsProperties(); //添加缓存 builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props); } } public Cache useNewCache(Class<? extends Cache> typeClass, Class<? extends Cache> evictionClass, Long flushInterval, Integer size, boolean readWrite, boolean blocking, Properties props) { //构建缓存 Cache cache = new CacheBuilder(currentNamespace) .implementation(valueOrDefault(typeClass, PerpetualCache.class)) .addDecorator(valueOrDefault(evictionClass, LruCache.class)) .clearInterval(flushInterval) .size(size) .readWrite(readWrite) .blocking(blocking) .properties(props) .build(); configuration.addCache(cache); //添加到configuration对象中 currentCache = cache; return cache; } public Cache build() { //设置默认实现 setDefaultImplementations(); //通过反射方式,来实例化缓存对象 Cache cache = newBaseCacheInstance(implementation, id); setCacheProperties(cache); // issue #352, do not apply decorators to custom caches if (PerpetualCache.class.equals(cache.getClass())) { for (Class<? extends Cache> decorator : decorators) { //装饰者装饰缓存对象 cache = newCacheDecoratorInstance(decorator, cache); setCacheProperties(cache); } cache = setStandardDecorators(cache); } else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) { cache = new LoggingCache(cache); } return cache; } //<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()); //id属性 String id = resultMapNode.getStringAttribute("id", resultMapNode.getValueBasedIdentifier()); //type属性 String type = resultMapNode.getStringAttribute("type", resultMapNode.getStringAttribute("ofType", resultMapNode.getStringAttribute("resultType", resultMapNode.getStringAttribute("javaType")))); //获取extends配置 String extend = resultMapNode.getStringAttribute("extends"); 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())) { //<constructor>子标签 processConstructorElement(resultChild, typeClass, resultMappings); } else if ("discriminator".equals(resultChild.getName())) { //<discriminator>子标签 discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings); } else { //<result>子标签 List<ResultFlag> flags = new ArrayList<ResultFlag>(); if ("id".equals(resultChild.getName())) { //<id>子标签 flags.add(ResultFlag.ID); } //构建resultMappings 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 ResultMapping buildResultMappingFromContext(XNode context, Class<?> resultType, List<ResultFlag> flags) throws Exception { String property; if (flags.contains(ResultFlag.CONSTRUCTOR)) { property = context.getStringAttribute("name"); } else { 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 resultSet = 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, resultSet, foreignColumn, lazy); } //解析<sql>标签 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 id = builderAssistant.applyCurrentNamespace(id, false); if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) { sqlFragments.put(id, context); } } } //在解析<select>等标签时,如何解析<include>标签 XMLIncludeTransformer includeParser = new XMLIncludeTransformer(configuration, builderAssistant); includeParser.applyIncludes(context.getNode()); //解析<include>标签 public void applyIncludes(Node source) { Properties variablesContext = new Properties(); Properties configurationVariables = configuration.getVariables(); if (configurationVariables != null) { //复制一份configuration对象中的全局变量 variablesContext.putAll(configurationVariables); } //应用包含的sql applyIncludes(source, variablesContext, false); } private void applyIncludes(Node source, final Properties variablesContext, boolean included) { if (source.getNodeName().equals("include")) { //如果是<include>标签 //提取refid对应的sql片段的Node Node toInclude = findSqlFragment(getStringAttribute(source, "refid"), variablesContext); Properties toIncludeContext = getVariablesContext(source, variablesContext); //将包含的sql片段节点作为参数递归此方法 applyIncludes(toInclude, toIncludeContext, true); if (toInclude.getOwnerDocument() != source.getOwnerDocument()) { toInclude = source.getOwnerDocument().importNode(toInclude, true); } //将当前节点替换成被包含节点 source.getParentNode().replaceChild(toInclude, source); while (toInclude.hasChildNodes()) { //将子节点放在被包含节点的前面 toInclude.getParentNode().insertBefore(toInclude.getFirstChild(), toInclude); } //从父节点中移除被包含节点 toInclude.getParentNode().removeChild(toInclude); } else if (source.getNodeType() == Node.ELEMENT_NODE) { if (included && !variablesContext.isEmpty()) { // replace variables in attribute values NamedNodeMap attributes = source.getAttributes(); for (int i = 0; i < attributes.getLength(); i++) { Node attr = attributes.item(i); attr.setNodeValue(PropertyParser.parse(attr.getNodeValue(), variablesContext)); } } NodeList children = source.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { applyIncludes(children.item(i), variablesContext, included); } } else if (included && source.getNodeType() == Node.TEXT_NODE && !variablesContext.isEmpty()) { // replace variables in text node source.setNodeValue(PropertyParser.parse(source.getNodeValue(), variablesContext)); } } private Node findSqlFragment(String refid, Properties variables) { //解析refid中声明的变量,形如:${} refid = PropertyParser.parse(refid, variables); //应用当前命名空间,命名空间+refid refid = builderAssistant.applyCurrentNamespace(refid, true); try { //根据refid从之前解析<sql/>标签时添加的映射中获取对应的节点 XNode nodeToInclude = configuration.getSqlFragments().get(refid); return nodeToInclude.getNode().cloneNode(true); } catch (IllegalArgumentException e) { throw new IncompleteElementException("Could not find SQL statement to include with refid '" + refid + "'", e); } }