根据架构图我们得知,mybatis加载初始化的第一步就是解析全局配置文件。
不清楚mybatis全局配置文件的查看这篇Mybatis全局配置文件解析
在不依赖spring的时候,我们可以这样得到SqlSessionFactory

  1. // 全局配置文件
  2. String resource = "SqlMapConfig.xml";
  3. InputStream inputStream = Resources.getResourceAsStream(resource);
  4. SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

构建SqlSessionFactory

这里使用了构建者模式,通过SqlSessionFactoryBuilder的build方法,构造出了SqlSessionFactory。

  1. public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
  2. try {
  3. // XMLConfigBuilder:用来解析XML配置文件
  4. // 使用构建者模式
  5. XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
  6. // parser.parse():使用XPATH解析XML配置文件,将配置文件封装为Configuration对象
  7. // 返回DefaultSqlSessionFactory对象,该对象拥有Configuration对象(封装配置文件信息)
  8. return build(parser.parse());
  9. } catch (Exception e) {
  10. throw ExceptionFactory.wrapException("Error building SqlSession.", e);
  11. } finally {
  12. ErrorContext.instance().reset();
  13. try {
  14. inputStream.close();
  15. } catch (IOException e) {
  16. // Intentionally ignore. Prefer previous error.
  17. }
  18. }
  19. }

构建XMLConfigBuilder,解析全局配置文件

这里的XMLConfigBuilder就是用来解析全局配置文件的,解析完了之后都封装在全局唯一的Configuration对象里。

  1. /**
  2. * 解析XML配置文件
  3. * @return
  4. */
  5. public Configuration parse() {
  6. if (parsed) {
  7. throw new BuilderException("Each XMLConfigBuilder can only be used once.");
  8. }
  9. parsed = true;
  10. // parser.evalNode("/configuration"):通过XPATH解析器,解析configuration根节点
  11. // 从configuration根节点开始解析,最终将解析出的内容封装到Configuration对象中
  12. parseConfiguration(parser.evalNode("/configuration"));
  13. return configuration;
  14. }
  15. private void parseConfiguration(XNode root) {
  16. try {
  17. //issue #117 read properties first
  18. // 解析</properties>标签
  19. propertiesElement(root.evalNode("properties"));
  20. // 解析</settings>标签
  21. Properties settings = settingsAsProperties(root.evalNode("settings"));
  22. loadCustomVfs(settings);
  23. loadCustomLogImpl(settings);
  24. // 解析</typeAliases>标签
  25. typeAliasesElement(root.evalNode("typeAliases"));
  26. // 解析</plugins>标签
  27. pluginElement(root.evalNode("plugins"));
  28. // 解析</objectFactory>标签
  29. objectFactoryElement(root.evalNode("objectFactory"));
  30. // 解析</objectWrapperFactory>标签
  31. objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
  32. // 解析</reflectorFactory>标签
  33. reflectorFactoryElement(root.evalNode("reflectorFactory"));
  34. settingsElement(settings);
  35. // read it after objectFactory and objectWrapperFactory issue #631
  36. // 解析</environments>标签
  37. environmentsElement(root.evalNode("environments"));
  38. // 解析</databaseIdProvider>标签
  39. databaseIdProviderElement(root.evalNode("databaseIdProvider"));
  40. // 解析</typeHandlers>标签
  41. typeHandlerElement(root.evalNode("typeHandlers"));
  42. // 解析</mappers>标签
  43. mapperElement(root.evalNode("mappers"));
  44. } catch (Exception e) {
  45. throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
  46. }
  47. }

这里就是一级一级的去解析我们的全局配置文件。

解析DataSource

environmentsElement这个方法就是解析我们的环境标签,里面包含了解析数据源,封装至DataSourceFactory对象中。

  1. private DataSourceFactory dataSourceElement(XNode context) throws Exception {
  2. if (context != null) {
  3. String type = context.getStringAttribute("type");
  4. Properties props = context.getChildrenAsProperties();
  5. DataSourceFactory factory = (DataSourceFactory) resolveClass(type).newInstance();
  6. factory.setProperties(props);
  7. return factory;
  8. }
  9. throw new BuilderException("Environment declaration requires a DataSourceFactory.");
  10. }
  1. public Properties getChildrenAsProperties() {
  2. Properties properties = new Properties();
  3. for (XNode child : getChildren()) {
  4. String name = child.getStringAttribute("name");
  5. String value = child.getStringAttribute("value");
  6. if (name != null && value != null) {
  7. properties.setProperty(name, value);
  8. }
  9. }
  10. return properties;
  11. }

解析mappers映射文件

三、解析mappers映射文件