mybatis中mapper生成代理的过程

目录

  1. mybatis中mapper代理的生成过程
  2. 与Spring集成时mapper代理的生成过程
  3. 与SpringBoot集成时mapper代理的生成过程

mybatis中mapper代理的生成过程

构建代理类工厂

从入口点开始一步一步看,首先SqlSessionFactoryBuilder类中build()方法加载配置文件

  public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
   
    try {
   
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      return build(parser.parse());
    } catch (Exception e) {
   
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
   
      // ...省略
    }
  }

将配置文件读取为XMLConfigBuilder对象,并调用parse()方法来解析文件,进到parse()

  public Configuration parse() {
     // ...省略
    parsed = true;
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
  }

可以看到具体的解析过程是在parseConfiguration方法中进行的。

  private void parseConfiguration(XNode root) {
   
    try {
   
       // ...省略
      //解析mapper
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
   
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }

这里重点看一下最后解析mapper的方法mapperElement(root.evalNode("mappers")),进到方法里,


  private void mapperElement(XNode parent) throws Exception {
   
    if (parent != null) {
   
      for (XNode child : parent.getChildren()) {
   
        if ("package".equals(child.getName())) {
   
          //   package 形式加载 ,加载package下的所有class文件
          String mapperPackage = child.getStringAttribute("name");
          configuration.addMappers(mapperPackage);
        } else {
   
          String resource = child.getStringAttribute("resource");
          String url = child.getStringAttribute("url");
          String mapperClass = child.getStringAttribute("class");
          if (resource != null && url == null && mapperClass == null) {
   
            // 通过Mapper.xml 加载
            ErrorContext.instance().resource(resource);
            InputStream inputStream = Resources.getResourceAsStream(resource);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
            mapperParser.parse();
          } else if (resource == null && url != null && mapperClass == null) {
   
            // 通过Mapper.xml 加载
            ErrorContext.instance().resource(url);
            InputStream inputStream = Resources.getUrlAsStream(url);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
            mapperParser.parse();
          } else if (resource == null && url == null && mapperClass != null) {
   
            // 通过单个class文件加载
            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.");
          }
        }
      }
    }
  }

整个mapperElement()方法就是加载mapper的过程了,可以看到加载mapper
有两种形式:通过class文件和通过xml文件。
构建mapper代理的过程也就是从这开始的,那就一步一步分析。
看一下通过XML文件加载的过程,mybatis将mapper相关的配置读取为一个XMLMapperBuilder对象,并通过parse()方法进行解析,进到这个方法中


  public void parse() {
   
    if (!configuration.isResourceLoaded(resource)) {
   
      // 加载xml文件
      configurationElement(parser.evalNode("/mapper"));
      configuration.addLoadedResource(resource);
      // 加载mapper class文件
      bindMapperForNamespace();
    }
   // ...省略
  }

parse()方法做了主要做了两件事,加载xml文件和加载class文件。
看一下加载xml的过程

  private void configurationElement(XNode context) {
   
    try {
   
      // 获取xml文件的namespace
      String namespace = context.getStringAttribute("namespace");
      if (namespace == null || namespace.equals("")) {
   
        throw new BuilderException("Mapper's namespace cannot be empty");
      }
      // 保存获取xml文件的namespace
      builderAssistant.setCurrentNamespace(namespace);
       // ...省略
    } catch (Exception e) {
   
      throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e);
    }
  }

本文是分析mapper代理的生成过程,所以加载xml的具体细节就不详细分析了,这里注意的是读取xml文件中namespace标签的值,并将值设置到builderAssistant对象中
现在回过头来看一下加载class文件的过程。进到bindMapperForNamespace()方法中去

  private void bindMapperForNamespace() {
   
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值