源码-mybatis-01-SqlSessionFactory创建

0.总概

 

 
1.SqlSessionFactory在mybatis只要创建一次;
import com.suntek.vdm.gw.util.AESEncipher;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.*;
import java.util.Properties;
 
/**
* @author Binglong
*/
public class MybatisUtils {
 
    private static SqlSessionFactory factory=null;
    /**
     * 获取SqlSessionFactory,只创建一次
     * @return SqlSessionFactory
     */
    private static SqlSessionFactory getSqlSessionFactory() {
        if (null != factory){
            return factory;
        }
        synchronized (SqlSessionFactory.class){
            factory = getFactory();
        }
        return factory;
    }
 
    private static SqlSessionFactory getFactory() {
        try {
            //读取配置文件
            Reader reader= Resources.getResourceAsReader("mybatis.xml");
            //创建SQLSessionFactory
            return new SqlSessionFactoryBuilder().build(reader);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

 

classpath路径下的mybatis.xml配置文件(以后详解配置文件)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--引入配置-->
    <properties resource="conf/db.properties"/>
    <!--sql打印 -->
    <!--<settings>-->
    <!--<setting name="logImpl" value="STDOUT_LOGGING"/>-->
    <!--</settings>-->
 
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="net.sourceforge.jtds.jdbc.Driver"/>
                <!--<property name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>-->
                <property name="url" value="${url}"/>
                <!--<property name="username" value="${username}"/>-->
                <!--<property name="password" value="${password}"/>-->
                <!--poolMaximumIdleConnections是空闲连接数,就是没有处理请求的连接,默认是5-->
                <property name="poolMaximumIdleConnections" value="5"/>
                <!--poolMaximumActiveConnections是最大的活动连接数,活动连接,就是正在与数据库交互的连接,默认是10-->
                <property name="poolMaximumActiveConnections" value="50"/>
                <!--<property name="poolPingQuery" value="SELECT 1 FROM VDM_VR_NODE" />-->
                <!--<property name="poolPingEnabled" value="true" />-->
            </dataSource>
        </environment>
    </environments>
 
    <mappers>
        <mapper resource="com/ned/gw/mapping/UserMapper.xml"></mapper>
    </mappers>
</configuration>
2.SqlSessionFactoryBuilder构建
从上面可以看到,SqlSessionFactory主要是由SqlSessionFactoryBuilder创建,而SqlSessionFactoryBuilder提供了两种方法创建,一种基于Reader,另一种基于InputStream;两种方式都是把配置封装成XMLConfigBuilder,然后通过 new DefaultSqlSessionFactory(config)创建;
有构造方法可以看,也要传入Properties 配置;
package org.apache.ibatis.session;
 
import java.io.*;
import java.util.Properties;
import org.apache.ibatis.builder.xml.XMLConfigBuilder;
import org.apache.ibatis.exceptions.ExceptionFactory;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
 
public class SqlSessionFactoryBuilder {
    public SqlSessionFactoryBuilder() {
    }
    public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
        SqlSessionFactory var5;
        try {
            XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
            var5 = this.build(parser.parse());
        } catch (Exception var14) {
            throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
        } finally {
            ErrorContext.instance().reset();
            try {
                reader.close();
            } catch (IOException var13) {
            }
        }
        return var5;
    }
 
 
    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
        SqlSessionFactory var5;
        try {
            XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
            var5 = this.build(parser.parse());
        } catch (Exception var14) {
            throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
        } finally {
            ErrorContext.instance().reset();
            try {
                inputStream.close();
            } catch (IOException var13) {
            }
        }
        return var5;
    }
 
    public SqlSessionFactory build(Configuration config) {
        return new DefaultSqlSessionFactory(config);
    }
}

 

3.XMLConfigBuilder解析
a.而XMLConfigBuilder最终把Reader和InputStream都封装成一个XPathParser(从字面上看估计是一个路径解析器);
b.获取到XMLConfigBuilder,还调用了其parse()方法,也就是解析配置文件(解析详情以后分析);
c.最终把所有配置封装在Configuration中,而这个Configuration正是SqlSessioFactory实现类DefaultSqlSessioFactory的重要属性;
值得关注的是这里XMLConfigBuilder创建时Properties props参数
public class XMLConfigBuilder extends BaseBuilder {
    private boolean parsed;
    private XPathParser parser;
    private String environment;
 
 
    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 (this.parsed) {
            throw new BuilderException("Each XMLConfigBuilder can only be used once.");
        } else {
            this.parsed = true;
            //从配置文件configuration节点作为根节点开始
            this.parseConfiguration(this.parser.evalNode("/configuration"));
            return this.configuration;
        }
    }
 
    //从这里可以看到,解析是按顺序解析,也就是平时配置文件的标签顺序
    private void parseConfiguration(XNode root) {
        try {
            this.propertiesElement(root.evalNode("properties"));
            this.typeAliasesElement(root.evalNode("typeAliases"));
            this.pluginElement(root.evalNode("plugins"));
            this.objectFactoryElement(root.evalNode("objectFactory"));
            this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
            this.settingsElement(root.evalNode("settings"));
            this.environmentsElement(root.evalNode("environments"));
            this.databaseIdProviderElement(root.evalNode("databaseIdProvider"));
            this.typeHandlerElement(root.evalNode("typeHandlers"));
            this.mapperElement(root.evalNode("mappers"));
        } catch (Exception var3) {
            throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + var3, var3);
        }
    }

}
public class XPathParser {
    private Document document ;
    private boolean validation; //是否开启验证
    private EntityResolver entityResolver ; //用于加载本地D T D 文件
    private Properties variables ; // mybatis.xml 中<propteries> 标签定义的键位对集合
    private XPath xpath ; // XPath 对象
}
public class DefaultSqlSessionFactory implements SqlSessionFactory {
    private final Configuration configuration;
    …………
}

 

 

4.总结
SqlSessionFactory创建过程是把配置文件通过InputStream或Reader两种方式传到SqlSessionFactoryBuilder,然后SqlSessionFactoryBuilder创建一个XMLConfigBuilder,把配置信息放到XMLConfigBuilder中然后调用parse方法进行一系列解析,最终生成一个Configuration,而这个Configuration正式DefaultSqlSessionFactory的唯一属性,也就是把Configuration传入new一个DefaultSqlSessionFactory;
 
 
遗留问题
mybaitis.xml解析解析细节;
Configuration类;
 
 
 
posted @ 2019-02-21 16:08  注册邮箱  阅读(262)  评论(0编辑  收藏  举报