您现在的位置是:亿华云 > 应用开发

Mybatis是如何解析配置文件的?看完终于明白了

亿华云2025-10-02 18:53:13【应用开发】4人已围观

简介在以前文章中,我们把Mybatis源码阅读的整个流程梳理了一遍。今天,我们来详细聊聊,Mybatis是如何解析配置文件的。这是今天分析的流程图:还是从案例开始。demo案例publicstaticvo

在以前文章中,解析我们把Mybatis源码阅读的配置整个流程梳理了一遍。今天,文件完终我们来详细聊聊,于明Mybatis是解析如何解析配置文件的。

这是配置今天分析的流程图:

还是从案例开始。

demo案例

public static void main(String[] args) {          String resource = "mybatis-config.xml";         InputStream inputStream = null;         SqlSession sqlSession = null;         try {              inputStream = Resources.getResourceAsStream(resource);             SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);             sqlSession = sqlSessionFactory.openSession();             UserMapper userMapper = sqlSession.getMapper(UserMapper.class);             System.out.println(userMapper.selectById(1));         } catch (Exception e) {              e.printStackTrace();         } finally {              try {                  inputStream.close();             } catch (IOException e) {                  e.printStackTrace();             }             sqlSession.close();         }     } 

见证奇迹

从SqlSessionFactoryBuilder开始。文件完终

SqlSessionFactoryBuilder类

org.apache.ibatis.session.SqlSessionFactoryBuilder 

该类里全是于明build方法各种重载。

//这个方法啥也没干   public SqlSessionFactory build(InputStream inputStream) {      return build(inputStream,解析 null, null);  } 

最终来到另外一个build方法里:

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {     try {       //创建一个XMLConfigBuilder对象        XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);      return build(parser.parse());    } catch (Exception e) {       throw ExceptionFactory.wrapException("Error building SqlSession.", e);    } finally {       ErrorContext.instance().reset();      try {         inputStream.close();      } catch (IOException e) {         // Intentionally ignore. Prefer previous error.      }    }  } 

XMLConfigBuilder类

该类的构造方法重载:

首先进入:

public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {      this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment,               props); } private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {      super(new Configuration());     ErrorContext.instance().resource("SQL Mapper Configuration");     this.configuration.setVariables(props);     this.parsed = false;     this.environment = environment;     this.parser = parser; } 

build(parser.parse());中的parser.parse();

mybatis-config.xml在哪里解析的呢?

请看下面这个方法:

//该方法返回一个Configuration对象 public Configuration parse() {    if (parsed) {      throw new BuilderException("Each XMLConfigBuilder can only be used once.");   }   parsed = true;   //关键点   parseConfiguration(parser.evalNode("/configuration"));   return configuration; } 

parseConfiguration(parser.evalNode("/configuration"));

终于看到开始解析配置文件了:

进入方法parseConfiguration。亿华云计算

private void parseConfiguration(XNode root) {    try {      //issue #117 read properties first     propertiesElement(root.evalNode("properties"));     Properties settings = settingsAsProperties(root.evalNode("settings"));     loadCustomVfs(settings);     loadCustomLogImpl(settings);     typeAliasesElement(root.evalNode("typeAliases"));     pluginElement(root.evalNode("plugins"));     objectFactoryElement(root.evalNode("objectFactory"));     objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));     reflectorFactoryElement(root.evalNode("reflectorFactory"));     settingsElement(settings);     // read it after objectFactory and objectWrapperFactory issue #631     environmentsElement(root.evalNode("environments"));     databaseIdProviderElement(root.evalNode("databaseIdProvider"));     typeHandlerElement(root.evalNode("typeHandlers"));     mapperElement(root.evalNode("mappers"));   } catch (Exception e) {      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e,配置 e);   } } 

这里就是把mybatis-config.xml内容解析,然后设置到Configuration对象中。文件完终

那么我们定义的于明Mapper.xml是在哪里解析的呢?

我们的Mapper.xml在mybatis-config.xml中的配置是这样的:

使用方式有以下四种:

//1使用类路径 <mappers>     <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>       <mapper resource="org/mybatis/builder/BlogMapper.xml"/>    <mapper resource="org/mybatis/builder/PostMapper.xml"/> </mappers> //2使用绝对url路径 <mappers>    <mapper url="file:///var/mappers/AuthorMapper.xml"/>    <mapper url="file:///var/mappers/BlogMapper.xml"/>    <mapper url="file:///var/mappers/PostMapper.xml"/> </mappers> //3使用java类名 <mappers>    <mapper class="org.mybatis.builder.AuthorMapper"/>    <mapper class="org.mybatis.builder.BlogMapper"/>    <mapper class="org.mybatis.builder.PostMapper"/> </mappers> //4自动扫描包下所有映射器 <mappers>    <package name="org.mybatis.builder"/> </mappers> 

继续源码分析,我们在上面mybatis-config.xml解析中可以看到:

我们不妨进入这个方法看看:

private void mapperElement(XNode parent) throws Exception {     if (parent != null) {       for (XNode child : parent.getChildren()) {         //自动扫描包下所有映射器        if ("package".equals(child.getName())) {           String mapperPackage = child.getStringAttribute("name");          //放            configuration.addMappers(mapperPackage);        } else {           String resource = child.getStringAttribute("resource");          String url = child.getStringAttribute("url");          String mapperClass = child.getStringAttribute("class");          //使用java类名          if (resource != null && url == null && mapperClass == null) {             ErrorContext.instance().resource(resource);             //根据文件存放目录,解析读取XxxMapper.xml            InputStream inputStream = Resources.getResourceAsStream(resource);             //映射器比较复杂,配置调用XMLMapperBuilder            //注意在for循环里每个mapper都重新new一个XMLMapperBuilder,文件完终来解析            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());            mapperParser.parse();          //使用绝对url路径          } else if (resource == null && url != null && mapperClass == null) {             ErrorContext.instance().resource(url);            InputStream inputStream = Resources.getUrlAsStream(url);            //映射器比较复杂,调用XMLMapperBuilder            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());            mapperParser.parse();          //使用类路径              } 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.");          }        }      }    }  } 

这里刚刚和我们的上面说的使用的源码下载方式完全是一模一样的。

到这里,配置文件mybatis-config.xml和我们定义映射文件XxxMapper.xml就全部解析完成。

回到SqlSessionFactoryBuilder类

前面讲到了XMLConfigBuilder中的parse方法,并返回了一个Configuration对象。

build(parser.parse());

这个build方法就是传入一个Configuration对象,然后构建一个DefaultSqlSession对象。

public SqlSessionFactory build(Configuration config) {    return new DefaultSqlSessionFactory(config); } 

继续回到我们的demo代码中这一行代码里:

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 

这一行代码就相当于:

SqlSessionFactory sqlSessionFactory = new new DefaultSqlSessionFactory(); 

到这里,我们的整个流程就搞定了。

本文转载自微信公众号「 Java后端技术全栈  」,可以通过以下二维码关注。转载本文请联系 Java后端技术全栈  公众号。源码库

很赞哦!(91345)