下面,分析 constructor 节点的解析过程。如下:
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 中添加 CONSTRUCTOR 标志 flags.add(ResultFlag.CONSTRUCTOR); if ("idArg".equals(argChild.getName())) { // 向 flags 中添加 ID 标志 flags.add(ResultFlag.ID); } // 构建 ResultMapping,上一节已经分析过 resultMappings.add(buildResultMappingFromContext(argChild, resultType, flags)); } }如上,上面方法的逻辑并不复杂。首先是获取并遍历子节点列表,然后为每个子节点创建 flags 集合,并添加 CONSTRUCTOR 标志。对于 idArg 节点,额外添加 ID 标志。最后一步则是构建 ResultMapping,该步逻辑前面已经分析过,这里就不多说了。
分析完 <resultMap> 的子节点 <id>,<result> 以及 <constructor> 的解析过程,下面来看看 ResultMap 实例的构建过程。
2.1.3.3 ResultMap 对象构建过程分析前面用了不少的篇幅来分析 <resultMap> 子节点的解析过程。通过前面的分析,我们可知 <id>,<result> 等节点最终都被解析成了 ResultMapping。在得到这些 ResultMapping 后,紧接着要做的事情是构建 ResultMap。如果说 ResultMapping 与单条结果映射相对应,那 ResultMap 与什么对应呢?答案是...。答案暂时还不能说,我们到源码中去找寻吧。下面,让我们带着这个疑问开始本节的源码分析。
前面分析了很多源码,大家可能都忘了 ResultMap 构建的入口了。这里再贴一下,如下:
private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings) throws Exception { // 获取 resultMap 节点中的属性 // ... // 解析 resultMap 对应的类型 // ... // 遍历 resultMap 节点的子节点,构建 ResultMapping 对象 // ... // 创建 ResultMap 解析器 ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping); try { // 根据前面获取到的信息构建 ResultMap 对象 return resultMapResolver.resolve(); } catch (IncompleteElementException e) { configuration.addIncompleteResultMap(resultMapResolver); throw e; } }如上,ResultMap 的构建逻辑分装在 ResultMapResolver 的 resolve 方法中,下面我从该方法进行分析。
// -☆- ResultMapResolver public ResultMap resolve() { return assistant.addResultMap(this.id, this.type, this.extend, this.discriminator, this.resultMappings, this.autoMapping); }上面的方法将构建 ResultMap 实例的任务委托给了 MapperBuilderAssistant 的 addResultMap,我们跟进到这个方法中看看。
// -☆- MapperBuilderAssistant public ResultMap addResultMap( String id, Class<?> type, String extend, Discriminator discriminator, List<ResultMapping> resultMappings, Boolean autoMapping) { // 为 ResultMap 的 id 和 extend 属性值拼接命名空间 id = applyCurrentNamespace(id, false); extend = applyCurrentNamespace(extend, true); if (extend != null) { 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()); // 为拓展 ResultMappings 取出重复项 extendedResultMappings.removeAll(resultMappings); boolean declaresConstructor = false; // 检测当前 resultMappings 集合中是否包含 CONSTRUCTOR 标志的元素 for (ResultMapping resultMapping : resultMappings) { if (resultMapping.getFlags().contains(ResultFlag.CONSTRUCTOR)) { declaresConstructor = true; break; } } /* * 如果当前 <resultMap> 节点中包含 <constructor> 子节点, * 则将拓展 ResultMapping 集合中的包含 CONSTRUCTOR 标志的元素移除 */ if (declaresConstructor) { Iterator<ResultMapping> extendedResultMappingsIter = extendedResultMappings.iterator(); while (extendedResultMappingsIter.hasNext()) { if (extendedResultMappingsIter.next().getFlags().contains(ResultFlag.CONSTRUCTOR)) { extendedResultMappingsIter.remove(); } } } // 将扩展 resultMappings 集合合并到当前 resultMappings 集合中 resultMappings.addAll(extendedResultMappings); } // 构建 ResultMap ResultMap resultMap = new ResultMap.Builder(configuration, id, type, resultMappings, autoMapping) .discriminator(discriminator) .build(); configuration.addResultMap(resultMap); return resultMap; }