mybatis执行过程梳理(1)——读取配置文件,生成连接

1,读取配置文件,生成连接

2,读取sql语句,生成sql语句——执行,得到结果,组装到结果集中


1,读取配置文件,生成连接

String resource = "mybatis.config.xml";
Reader reader = Resources.getResourceAsReader(resource);  \\读取到配置文件,将文件以输入流的方式读取到内存中
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);
SqlSession ss = ssf.openSession();

SqlSessionFactoryBuilder类中重载了9个build方法。前4个的配置输入是 Reader 。后4个的配置输入是 InputStreatm 。最后一个直接返回默认的连接工厂类。
两个生成连接工厂的方法写法几乎完全一致,通过创建一个XMLConfigBuilder对象,执行其parse()方法得到一个Configuration,把这个Configuration传入最后一个构造方法生成 连接工厂类

    public SqlSessionFactory build(Reader reader) {
        return this.build((Reader)reader, (String)null, (Properties)null);
    }

    public SqlSessionFactory build(Reader reader, String environment) {
        return this.build((Reader)reader, environment, (Properties)null);
    }

    public SqlSessionFactory build(Reader reader, Properties properties) {
        return this.build((Reader)reader, (String)null, properties);
    }

    public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
        SqlSessionFactory var5;

        。。。

        XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
        var5 = this.build(parser.parse());

        。。。

        return var5;
    }

    public SqlSessionFactory build(InputStream inputStream) {
        return this.build((InputStream)inputStream, (String)null, (Properties)null);
    }

    public SqlSessionFactory build(InputStream inputStream, String environment) {
        return this.build((InputStream)inputStream, environment, (Properties)null);
    }

    public SqlSessionFactory build(InputStream inputStream, Properties properties) {
        return this.build((InputStream)inputStream, (String)null, properties);
    }

    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
        SqlSessionFactory var5;

    。。。

        XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
        var5 = this.build(parser.parse());

    。。。       

        return var5;
    }

    public SqlSessionFactory build(Configuration config) {return new DefaultSqlSessionFactory(config);}

XMLConfigBuilder的作用就是解析mybatis的配置文件,然后根据配置生成连接工厂。
XMLConfigBuilder有以下4个私有属性

private boolean parsed;  //是否解析过
private final XPathParser parser;  //配置文件路径
private String environment;  //配置文件里的环境,没有指定就使用默认的
private final ReflectorFactory localReflectorFactory;

XMLConfigBuilder中重载了多个构造方法以根据不同参数来构造对象,所有的构造方法都指向了一个私有的构造方法。这里需要一个XPathParser对象,以及前面传过来的两个参数

public XMLConfigBuilder(Reader reader, String environment, Properties props) {
    this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props);
}
public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
    this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
}

private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
    super(new Configuration());
    this.localReflectorFactory = new DefaultReflectorFactory(); //反射工厂,用来返回sql中指定的类信息
    ErrorContext.instance().resource("SQL Mapper Configuration");
    this.configuration.setVariables(props);
    this.parsed = false;  //默认没有解析过,解析之后这里变为true,只能解析一次
    this.environment = environment;  //配置文件中的环境
    this.parser = parser;
}

parse()方法是比较重要的。首先判断是否解析过配置,这里只能解析一次(解析一次就得到了全部信息,貌似就没必要进行第二次了,浪费资源)。解析配置调用parseConfiguration()方法解析配置文件

public Configuration parse() {
        if (this.parsed) {
            throw new BuilderException("Each XMLConfigBuilder can only be used once.");
        } else {
            this.parsed = true;
            this.parseConfiguration(this.parser.evalNode("/configuration"));
            return this.configuration;
        }
    }

parseConfiguration方法是读取配置文件保存到类中的核心方法。
在此,将配置配置文件中的各个标签下的属性都读取到类中保存。该类是Configuration的一个实体类,并且是XMLConfigBuilder的一个 protected 的属性(继承自BaseBuilder)。得到的这个Configuration最终作为参数传入SqlSessionFactoryBuilder的构造方法中,得到连接工厂类

private void parseConfiguration(XNode root) {
        try {
            this.propertiesElement(root.evalNode("properties"));
            Properties settings = this.settingsAsProperties(root.evalNode("settings"));
            this.loadCustomVfs(settings);
            this.typeAliasesElement(root.evalNode("typeAliases"));
            this.pluginElement(root.evalNode("plugins"));
            this.objectFactoryElement(root.evalNode("objectFactory"));
            this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
            this.reflectorFactoryElement(root.evalNode("reflectorFactory"));
            this.settingsElement(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);
        }
    }

DefaultSqlSessionFactory类中只有一个构造方法,一堆重载的openSession()方法,而最终指向的有两个私有方法,这两个私有方法最终都返回了DefaultSqlSession(实现了SqlSession接口)。Session创建成功

public class DefaultSqlSessionFactory implements SqlSessionFactory {
    private final Configuration configuration;
    public DefaultSqlSessionFactory(Configuration configuration) {
        this.configuration = configuration;
    }

    //这里是一堆重载的 openSession 方法

     private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
        Transaction tx = null;
        DefaultSqlSession var8;
        try {
            Environment environment = this.configuration.getEnvironment();
            TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
            tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
            Executor executor = this.configuration.newExecutor(tx, execType);
            var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
        } catch (Exception var12) {
            this.closeTransaction(tx);
            throw ExceptionFactory.wrapException("Error opening session.  Cause: " + var12, var12);
        } finally {
            ErrorContext.instance().reset();
        }

        return var8;
    }

    private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
        DefaultSqlSession var8;
        try {
            boolean autoCommit;
            try {
                autoCommit = connection.getAutoCommit();
            } catch (SQLException var13) {
                autoCommit = true;
            }

            Environment environment = this.configuration.getEnvironment();
            TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
            Transaction tx = transactionFactory.newTransaction(connection);
            Executor executor = this.configuration.newExecutor(tx, execType);
            var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
        } catch (Exception var14) {
            throw ExceptionFactory.wrapException("Error opening session.  Cause: " + var14, var14);
        } finally {
            ErrorContext.instance().reset();
        }

        return var8;
    }
}

第一次写,权当自己做的笔记吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值