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;
    }
}

第一次寫,權當自己做的筆記吧!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章