加载完资源文件,下一步就是构建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSessionFactoryBuilder类主要方法有下面两个:
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { try { //第一步,构建XMLConfigBuilder对象 XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); return build(parser.parse()/*第二步,生成Configuration对象*/)//第三步,生成DefaultSqlSessionFactory; } 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. } } } public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); }
构建sqlSessionFactory主要分3步:
第一步:根据配置文件、环境变量和properties构建XMLConfigBuilder对象。
第二步:.XMLConfigBuilder对象生成Configuration对象(parser.parse()方法)。
第三步:.根据Configuration对象生成DefaultSqlSessionFactory。
通过以上三步,文章开头的sqlSessionFactory的值等于一个DefaultSqlSessionFactory对象,构建sqlSessionFactory完成。下面我们对涉及到类和方法详细介绍。
SqlSessionFactoryBuilder是一个构建sqlSessionFactory的工具类,提供了一些重载的方法,主要的方法就是上面介绍的两个。
XMLConfigBuilder是BaseBuilder的众多子类之一,XMLConfigBuilder扮演的是具体建造者的角色,BaseBuilder扮演的是抽象建造者的角色。BaseBuilder 中核心宇段的含义如下:
//Configuration MyBatis初始化过程的核心对象,MyBatis中几乎全部的配置信息会保存到Configuration对象中 //Configuration对象是在MyBatis初始化过程中创建且是全局唯一的,也有人称它是一个“All-In-One ”配置对象 protected final Configuration configuration; //在 mybatis-config xml配置文件中可以使用<typeAliases>标签定义别名,这些定义的别名都会记录在TypeAliasRegistry对象中 protected final TypeAliasRegistry typeAliasRegistry; //mybatis-config.xml配置文件中可以使用<typeHandlers>标签添加自定义TypeHandler完成数据库类型与Java类型的转换 protected final TypeHandlerRegistry typeHandlerRegistry;
typeAliasRegistry与typeHandlerRegistry,都是从configuratioin中来,所以也是全局唯一的,从BaseBuilder的构造函数可以看出:
public BaseBuilder(Configuration configuration) { this.configuration = configuration; this.typeAliasRegistry = this.configuration.getTypeAliasRegistry(); this.typeHandlerRegistry = this.configuration.getTypeHandlerRegistry(); }
XMLConfigBuilder主要负责解析mybatis-config.xml 配置文件,生成Configuration对象,代码如下:
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; } public Configuration parse() { if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true; parseConfiguration(parser.evalNode("/configuration")); return configuration; }
可以看到在XMLConfigBuilder的构造方法中new了一个Configuration对象,在parse()方法中通过parseConfiguration()方法解析xml文件,并赋值到configuration。其中parser.evalNode("/configuration")的作用是把/configuration节点封装成XNode对象,作为parseConfiguration()方法的参数。
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); } }
可以看到这个方法是解析各个节点,并赋值到configuration对象。
下一节详细讲解各个节点的解析赋值。