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

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

创新互联为您提适合企业的网站设计 让您的网站在搜索引擎具有高度排名,让您的网站具备超强的网络竞争力!结合企业自身,进行网站设计及把握,最后结合企业文化和具体宗旨等,才能创作出一份性化解决方案。从网站策划到成都网站制作、网站设计, 我们的网页设计师为您提供的解决方案。

这是今天分析的流程图:

还是从案例开始。

demo案例

 
 
 
 
  1. public static void main(String[] args) { 
  2.         String resource = "mybatis-config.xml"; 
  3.         InputStream inputStream = null; 
  4.         SqlSession sqlSession = null; 
  5.         try { 
  6.             inputStream = Resources.getResourceAsStream(resource); 
  7.             SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 
  8.             sqlSession = sqlSessionFactory.openSession(); 
  9.  
  10.             UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 
  11.             System.out.println(userMapper.selectById(1)); 
  12.  
  13.         } catch (Exception e) { 
  14.             e.printStackTrace(); 
  15.         } finally { 
  16.             try { 
  17.                 inputStream.close(); 
  18.             } catch (IOException e) { 
  19.                 e.printStackTrace(); 
  20.             } 
  21.             sqlSession.close(); 
  22.         } 
  23.     } 

见证奇迹

从SqlSessionFactoryBuilder开始。

SqlSessionFactoryBuilder类

 
 
 
 
  1. org.apache.ibatis.session.SqlSessionFactoryBuilder 

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

 
 
 
 
  1. //这个方法啥也没干   
  2. public SqlSessionFactory build(InputStream inputStream) { 
  3.     return build(inputStream, null, null); 
  4.  } 

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

 
 
 
 
  1. public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { 
  2.    try { 
  3.      //创建一个XMLConfigBuilder对象   
  4.      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); 
  5.      return build(parser.parse()); 
  6.    } catch (Exception e) { 
  7.      throw ExceptionFactory.wrapException("Error building SqlSession.", e); 
  8.    } finally { 
  9.      ErrorContext.instance().reset(); 
  10.      try { 
  11.        inputStream.close(); 
  12.      } catch (IOException e) { 
  13.        // Intentionally ignore. Prefer previous error. 
  14.      } 
  15.    } 
  16.  } 

XMLConfigBuilder类

该类的构造方法重载:

首先进入:

 
 
 
 
  1. public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) { 
  2.     this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment,      
  3.          props); 
  4. private XMLConfigBuilder(XPathParser parser, String environment, Properties props) { 
  5.     super(new Configuration()); 
  6.     ErrorContext.instance().resource("SQL Mapper Configuration"); 
  7.     this.configuration.setVariables(props); 
  8.     this.parsed = false; 
  9.     this.environment = environment; 
  10.     this.parser = parser; 

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

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

请看下面这个方法:

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

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

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

进入方法parseConfiguration。

 
 
 
 
  1. private void parseConfiguration(XNode root) { 
  2.   try { 
  3.     //issue #117 read properties first 
  4.     propertiesElement(root.evalNode("properties")); 
  5.     Properties settings = settingsAsProperties(root.evalNode("settings")); 
  6.     loadCustomVfs(settings); 
  7.     loadCustomLogImpl(settings); 
  8.     typeAliasesElement(root.evalNode("typeAliases")); 
  9.     pluginElement(root.evalNode("plugins")); 
  10.     objectFactoryElement(root.evalNode("objectFactory")); 
  11.     objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); 
  12.     reflectorFactoryElement(root.evalNode("reflectorFactory")); 
  13.     settingsElement(settings); 
  14.     // read it after objectFactory and objectWrapperFactory issue #631 
  15.     environmentsElement(root.evalNode("environments")); 
  16.     databaseIdProviderElement(root.evalNode("databaseIdProvider")); 
  17.     typeHandlerElement(root.evalNode("typeHandlers")); 
  18.     mapperElement(root.evalNode("mappers")); 
  19.   } catch (Exception e) { 
  20.     throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); 
  21.   } 

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

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

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

使用方式有以下四种:

 
 
 
 
  1. //1使用类路径 
  2.  
  3.      
  4.        
  5.     
  6.  
  7. //2使用绝对url路径 
  8.  
  9.     
  10.     
  11.     
  12.  
  13. //3使用java类名 
  14.  
  15.     
  16.     
  17.     
  18.  
  19.  
  20. //4自动扫描包下所有映射器 
  21.  
  22.     
  23.  

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

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

 
 
 
 
  1. private void mapperElement(XNode parent) throws Exception { 
  2.    if (parent != null) { 
  3.      for (XNode child : parent.getChildren()) { 
  4.        //自动扫描包下所有映射器 
  5.        if ("package".equals(child.getName())) { 
  6.          String mapperPackage = child.getStringAttribute("name"); 
  7.          //放   
  8.          configuration.addMappers(mapperPackage); 
  9.        } else { 
  10.          String resource = child.getStringAttribute("resource"); 
  11.          String url = child.getStringAttribute("url"); 
  12.          String mapperClass = child.getStringAttribute("class"); 
  13.          //使用java类名 
  14.          if (resource != null && url == null && mapperClass == null) { 
  15.            ErrorContext.instance().resource(resource); 
  16.             //根据文件存放目录,读取XxxMapper.xml 
  17.            InputStream inputStream = Resources.getResourceAsStream(resource); 
  18.             //映射器比较复杂,调用XMLMapperBuilder 
  19.            //注意在for循环里每个mapper都重新new一个XMLMapperBuilder,来解析 
  20.            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments()); 
  21.            mapperParser.parse(); 
  22.          //使用绝对url路径 
  23.          } else if (resource == null && url != null && mapperClass == null) { 
  24.            ErrorContext.instance().resource(url); 
  25.            InputStream inputStream = Resources.getUrlAsStream(url); 
  26.            //映射器比较复杂,调用XMLMapperBuilder 
  27.            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments()); 
  28.            mapperParser.parse(); 
  29.          //使用类路径     
  30.          } else if (resource == null && url == null && mapperClass != null) { 
  31.            Class mapperInterface = Resources.classForName(mapperClass); 
  32.            //直接把这个映射加入配置 
  33.            configuration.addMapper(mapperInterface); 
  34.          } else { 
  35.            throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one."); 
  36.          } 
  37.        } 
  38.      } 
  39.    } 
  40.  } 

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

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

回到SqlSessionFactoryBuilder类

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

build(parser.parse());

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

 
 
 
 
  1. public SqlSessionFactory build(Configuration config) { 
  2.   return new DefaultSqlSessionFactory(config); 

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

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

这一行代码就相当于:

 
 
 
 
  1. SqlSessionFactory sqlSessionFactory = new new DefaultSqlSessionFactory(); 

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

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

网站标题:Mybatis是如何解析配置文件的?看完终于明白了
URL网址:http://www.shufengxianlan.com/qtweb/news28/396878.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联