根据架构图我们得知,mybatis加载初始化的第一步就是解析全局配置文件。
不清楚mybatis全局配置文件的查看这篇Mybatis全局配置文件解析
在不依赖spring的时候,我们可以这样得到SqlSessionFactory
// 全局配置文件String resource = "SqlMapConfig.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
构建SqlSessionFactory
这里使用了构建者模式,通过SqlSessionFactoryBuilder的build方法,构造出了SqlSessionFactory。
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {try {// XMLConfigBuilder:用来解析XML配置文件// 使用构建者模式XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);// parser.parse():使用XPATH解析XML配置文件,将配置文件封装为Configuration对象// 返回DefaultSqlSessionFactory对象,该对象拥有Configuration对象(封装配置文件信息)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,解析全局配置文件
这里的XMLConfigBuilder就是用来解析全局配置文件的,解析完了之后都封装在全局唯一的Configuration对象里。
/*** 解析XML配置文件* @return*/public Configuration parse() {if (parsed) {throw new BuilderException("Each XMLConfigBuilder can only be used once.");}parsed = true;// parser.evalNode("/configuration"):通过XPATH解析器,解析configuration根节点// 从configuration根节点开始解析,最终将解析出的内容封装到Configuration对象中parseConfiguration(parser.evalNode("/configuration"));return configuration;}private void parseConfiguration(XNode root) {try {//issue #117 read properties first// 解析</properties>标签propertiesElement(root.evalNode("properties"));// 解析</settings>标签Properties settings = settingsAsProperties(root.evalNode("settings"));loadCustomVfs(settings);loadCustomLogImpl(settings);// 解析</typeAliases>标签typeAliasesElement(root.evalNode("typeAliases"));// 解析</plugins>标签pluginElement(root.evalNode("plugins"));// 解析</objectFactory>标签objectFactoryElement(root.evalNode("objectFactory"));// 解析</objectWrapperFactory>标签objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));// 解析</reflectorFactory>标签reflectorFactoryElement(root.evalNode("reflectorFactory"));settingsElement(settings);// read it after objectFactory and objectWrapperFactory issue #631// 解析</environments>标签environmentsElement(root.evalNode("environments"));// 解析</databaseIdProvider>标签databaseIdProviderElement(root.evalNode("databaseIdProvider"));// 解析</typeHandlers>标签typeHandlerElement(root.evalNode("typeHandlers"));// 解析</mappers>标签mapperElement(root.evalNode("mappers"));} catch (Exception e) {throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);}}
解析DataSource
environmentsElement这个方法就是解析我们的环境标签,里面包含了解析数据源,封装至DataSourceFactory对象中。
private DataSourceFactory dataSourceElement(XNode context) throws Exception {if (context != null) {String type = context.getStringAttribute("type");Properties props = context.getChildrenAsProperties();DataSourceFactory factory = (DataSourceFactory) resolveClass(type).newInstance();factory.setProperties(props);return factory;}throw new BuilderException("Environment declaration requires a DataSourceFactory.");}
public Properties getChildrenAsProperties() {Properties properties = new Properties();for (XNode child : getChildren()) {String name = child.getStringAttribute("name");String value = child.getStringAttribute("value");if (name != null && value != null) {properties.setProperty(name, value);}}return properties;}
