根據XML配置文件構建SqlSessionFactory
1. 首先讀取類路徑下的配置文件,獲取其字節輸入流。
2. 創建SqlSessionFactoryBuilder對象,調用內部的build方法。factory = new SqlSessionFactoryBuilder().build(in);
3. 根據字節輸入流創建XMLConfigBuilder即解析器對象parser。
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
4. 調用parser對象的parse方法,parser.parse(),該結果將返回一個Configuration配置對象,作為build方法的參數。
5. parse()方法中,調用parseConfiguration方法將Configuration元素下的所有配置信息封裝進Parser對象的成員Configuration對象之中。
6. 其中進行解析xml元素的方式是將通過evalNode方法獲取對應名稱的節點信息。如:parseConfiguration(parser.evalNode("/configuration"));,此時parser.evalNode("/configuration")即為Configuration下的所有信息。
7. parseConfiguration方法相當於將裡面每個元素的信息都單獨封裝到Configuration中。
值得一提的是,我們之後要分析基於代理模式產生dao的代理對象涉及到mappers的封裝,其實也在配置文件讀取封裝的時候就已經完成,也就是在parseConfiguration方法之中:mapperElement(root.evalNode("mappers"));。他的作用就是,讀取我們主配置文件中<mappers>的元素內容,也就是我們配置的映射配置文件。
private void mapperElement(XNode parent)方法將mappers配置下的信息獲取,此處獲取我們resources包下的com.smday.dao包名。
接著就調用了configuration的addMappers方法,其實還是調用的是mapperRegistry。
讀到這裡,我們就會漸漸了解MapperRegistry這個類的職責所在,接著來看,這個類中進行的一些工作,在每次添加mappers的時候,會利用ResolverUtil類查找類路徑下的該包名路徑下,是否有滿足條件的類,如果有的話,就將Class對象添加進去,否則報錯。
緊接著,就到了一步比較重要的部分,當然只是我個人覺得,因為第一遍看的時候,我沒有想到,這步居然可以封裝許許多多的重要信息,我們來看一看:
映射配置文件的讀取依靠namespace,我們可以通過查看源碼發現讀取映射配置文件的方法是loadXmlResouce(),所以namespace命名空間至關重要:
可以看到,對映射文件解析之後,mappedStatements對象中出現了以下內容:
至此,主配置文件和映射配置文件的配置信息就已經讀取完畢。
8. 最後依據獲得的Configuration對象,創建一個new DefaultSqlSessionFactory(config)。
總結:
解析配置文件的信息,並保存在Configuration對象中。返回包含Configuration的DefaultSqlSession對象。通過SqlSessionFactory創建SqlSession
1. 調用SqlSessionFactory對象的openSession方法,其實是調用
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)
方法,通過參數就可以知道,分別是執行器的類型,事務隔離級別和設置是否自動提交,因此,我們就可以得知,我們在創建SqlSession的時候可以指定這些屬性。
2. 從configuration中獲取environment、dataSource和transactionFactory信息,創建事務對象Transaction。
補充:後續看了一些博客,說是保證executor不為空,因為defaultExecutorType有可能為空。
3. 根據配置信息,執行器信息和自動提交信息創建DefaultSqlSession。
getMapper獲取動態代理對象
下面這句話意思非常明了,就是通過傳入接口類型對象,獲取接口代理對象。
IUserDao userDao1 = sqlSession1.getMapper(IUserDao.class);
具體的過程如下:
1. 首先,調用SqlSession的實現類DefaultSqlSession的getMapper方法,其實是在該方法內調用configuration的getMapper方法,將接口類對象以及當前sqlsession對象傳入。
2. 接著調用我們熟悉的mapperRegistry,因為我們知道,在讀取配置文件,創建sqlSession的時候,接口類型信息就已經被存入到其內部維護的Map之中。
3. 我們來看看getMapper方法具體的實現如何:
4. 緊接著,我們進入MapperProxyFactory,真真實實地發現了創建代理對象的過程。