MyBatis源码解析(三) --- 映射文件解析

本文详细解析了MyBatis映射文件的配置及解析流程,包括映射文件的加载方式、解析入口及核心操作,如mapper节点解析、Mapper接口绑定及未完成节点处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

映射文件用于配置 SQL 语句,字段映射关系等。映射文件中包含< cache >、< cache-ref >、< resultMap >、< sql >、 <select|insert|update|delete>等二级节点,这些节点将在接下来内容中进行分析。

1、映射文件解析解析入口

映射文件的解析过程是配置文件解析过程的一部分,MyBatis 会在解析配置文件的过程 中对映射文件进行解析。解析逻辑封装在 mapperElement 方法中,下面来看一下。

// -☆- XMLConfigBuilder
private void mapperElement(XNode parent) throws Exception {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
      // 获取 <package> 节点中的 name 属性
        if ("package".equals(child.getName())) {
          String mapperPackage = child.getStringAttribute("name");
          // 从指定包中查找 mapper 接口,并根据 mapper 接口解析映射配置
          configuration.addMappers(mapperPackage);
        } else {
        // 获取 resource/url/class 等属性
          String resource = child.getStringAttribute("resource");
          String url = child.getStringAttribute("url");
          String mapperClass = child.getStringAttribute("class");

          // resource 不为空,且其他两者为空,则从指定路径中加载配置
          if (resource != null && url == null && mapperClass == null) {
            ErrorContext.instance().resource(resource);
            InputStream inputStream = Resources.getResourceAsStream(resource);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
            mapperParser.parse();
            // url 不为空,且其他两者为空,则通过 url 加载配置
          } else if (resource == null && url != null && mapperClass == null) {
            ErrorContext.instance().resource(url);
            InputStream inputStream = Resources.getUrlAsStream(url);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
            // 解析映射文件
            mapperParser.parse();
            // mapperClass不为空,且其他两者为空, 
            // 则通过mapperClass解析映射配置
          } else if (resource == null && url == null && mapperClass != null) {
            Class<?> mapperInterface = Resources.classForName(mapperClass);
            configuration.addMapper(mapperInterface);
          } else {
            throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
          }
        }
      }
    }
  }

上面代码的主要逻辑是遍历 mappers 的子节点,并根据节点属性值判断通过何种方式加 载映射文件或映射信息。这里把配置在注解中的内容称为映射信息,以 XML 为载体的配置 称为映射文件。

在 MyBatis 中,共有四种加载映射文件或映射信息的方式。

  • 第一种是从文件 系统中加载映射文件;
  • 第二种是通过 URL 的方式加载映射文件;
  • 第三种是通过 mapper 接口 加载映射信息,映射信息可以配置在注解中,也可以配置在映射文件中。
  • 第四种是通过包 扫描的方式获取到某个包下的所有类,并使用第三种方式为每个类解析映射信息。

下面开始分析映射文件的解析过程,在分析之前,先来看一下映射文件解析入口。

  public void parse() {
   // 检测映射文件是否已经被解析过
    if (!configuration.isResourceLoaded(resource)) {
      // 解析 mapper 节点
      configurationElement(parser.evalNode("/mapper"));
      // 添加资源路径到“已解析资源集合”中
      configuration.addLoadedResource(resource);
      // 通过命名空间绑定 Mapper 接口
      bindMapperForNamespace();
    }
    // 处理未完成解析的节点
    parsePendingResultMaps();
    parsePendingCacheRefs();
    parsePendingStatements();
  }

映射文件解析入口逻辑包含三个核心操作,如下:

  1. 解析 mapper 节点
  2. 通过命名空间绑定 Mapper 接口
  3. 处理未完成解析的节点
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值