一.mybaties源碼
- 1.加載mybatis-config.xml配置文件
- 2.通過配置文件創(chuàng)建SqlSessionFactory
解析 properties節(jié)點
<properties resource="db.properties"></properties>
解析我們的mybatis-config.xml中的settings節(jié)點
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
解析我們的別名
解析我們的插件(比如分頁插件)<plugins> <plugin interceptor="com.hehe.plugins.ExamplePlugin" ></plugin> </plugins>
解析我們的mybatis環(huán)境
解析數(shù)據(jù)庫廠商
解析我們的類型處理器節(jié)點
解析我們的mapper<mappers> <!--1.必須保證接口名(例如IUserDao)和xml名(IUserDao.xml)相同啸如,還必須在同一個包中--> <package name="com.hehe.mapper"/> <!--2.不用保證同接口同包同名 <mapper resource="com/mybatis/mappers/EmployeeMapper.xml"/> 3.保證接口名(例如IUserDao)和xml名(IUserDao.xml)相同,還必須在同一個包中 <mapper class="com.mybatis.dao.EmployeeMapper"/> 4.不推薦:引用網路路徑或者磁盤路徑下的sql映射文件 file:///var/mappers/AuthorMapper.xml <mapper url="file:E:/Study/myeclipse/_03_Test/src/cn/sdut/pojo/PersonMapper.xml"/>--> </mappers>
3.通過sqlSessionFactory獲取SqlSession(數(shù)據(jù)源執(zhí)行器)
- 獲取事務工廠
- 創(chuàng)建一個sql執(zhí)行器對象
- 構造DefaultSqlSession
4.SqlSession進行CRUD或者動態(tài)代理創(chuàng)建mapper類 - 根據(jù)statement獲取MappedStatement
- 參數(shù)和MappedStatement組裝成sql
- 生成緩存key
-判斷是否開啟二級緩存氮惯,有就去二級緩存在叮雳,沒有或者找不到就去查數(shù)據(jù)庫(BaseExecutor的query方法) - 判斷以及緩存是否有,沒有就去查數(shù)據(jù)庫妇汗,查到并放入一級緩存悲关。
對象介紹
Executor
1.根據(jù)用戶選擇的執(zhí)行器類型腊满,構造出BatchExecutor、ReuseExecutor、SimpleExecutor
- BatchExecutor 批量插入的時候可以使用這個
- ReuseExecutor 可重復使用的連接
- SimpleExecutor 一次性連接航夺,操作完后便銷毀
2.如果全局配置開啟緩存,則Executor進一步封裝成CachingExecutor饱搏,每次查詢會走緩存
3.如果使用了插件叭披,則會調用動態(tài)代理和責任鏈,生成插件Executor
Cache
二級緩存
裝飾器模式慈参,如圖:
public Cache build() {
// 默認PerpetualCache呛牲,最終的map緩存sql結果
// 如果沒有設置淘汰策略,默認使用LRU
setDefaultImplementations();
// 反射獲取PerpetualCache
Cache cache = newBaseCacheInstance(implementation, id);
setCacheProperties(cache);
// issue #352, do not apply decorators to custom caches 不將裝飾器應用到自定義緩存
if (PerpetualCache.class.equals(cache.getClass())) {
for (Class<? extends Cache> decorator : decorators) {
// 獲取默認的LruCache
cache = newCacheDecoratorInstance(decorator, cache);
setCacheProperties(cache);
}
// 如果設置了clearInterval驮配,則會使用ScheduledCache:調度緩存娘扩,負責定時清空緩存
// SerializedCache.默認使用,序列化和反序列化存儲
// LoggingCache 默認使用,記錄緩存命中
// SynchronizedCache 默認開啟壮锻,并發(fā)控制
// BlockingCache 默認不開啟琐旁,使用ReentrantLock,鎖的粒度更細
cache = setStandardDecorators(cache);
} else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) {
cache = new LoggingCache(cache);
}
return cache;
}
TransactionalCache:每個事物都有一個緩存區(qū)躯保,稱之為暫存區(qū)旋膳,如果AutoCommit設置為true,則二級緩存是不生效的途事,只有執(zhí)行commit的時候验懊,才會清理暫存區(qū)和更新二級緩存擅羞,這樣就不會臟讀了。
一級緩存
每個查詢(一個事物)都會把查詢緩存起來义图,當同事物同一個sql就會使用到一級緩存减俏,所以當你整合到spring使用spring的事物的時候,那么一級緩存就失效了碱工。
BaseBuilder相關類
- XMLConfigBuilder
解析全局配置文件娃承,內部的mapper使用XMLMapperBuilder解析 - XMLMapperBuilder
解析所有的mapper.xml,內部的的節(jié)點使用XMLStatementBuilder解析 - XMLStatementBuilder
解析xml的各個節(jié)點(select怕篷、update等)历筝,內部使用XMLScriptBuilder處理sql部分 - XMLScriptBuilder
解析xml中各個節(jié)點sql部分的Builder。
MyBatissql語句的解析過程
- SqlNode
xml中一個個標簽廊谓,比如上述sql的update,trim,if標簽梳猪。 - SqlSource
由SqlNode構成,用于獲取BoundSql - BoundSql
最終產生sql的類蒸痹,包括sql語句春弥,參數(shù),參數(shù)源數(shù)據(jù)等參數(shù)
設計模式
Builder模式叠荠,例如SqlSessionFactoryBuilder匿沛、XMLConfigBuilder、XMLMapperBuilder榛鼎、XMLStatementBuilder逃呼、CacheBuilder;
工廠模式借帘,例如SqlSessionFactory蜘渣、ObjectFactory、MapperProxyFactory肺然;
單例模式蔫缸,例如ErrorContext和LogFactory;
代理模式际起,Mybatis實現(xiàn)的核心拾碌,比如MapperProxy、ConnectionLogger街望,用的jdk的動態(tài)代理校翔;還有executor.loader包使用了cglib或者javassist達到延遲加載的效果;
組合模式灾前,例如SqlNode和各個子類ChooseSqlNode等防症;
模板方法模式,例如BaseExecutor和SimpleExecutor,還有BaseTypeHandler和所有的子類例如IntegerTypeHandler蔫敲;
適配器模式饲嗽,例如Log的Mybatis接口和它對jdbc、log4j等各種日志框架的適配實現(xiàn)奈嘿;
裝飾者模式貌虾,例如Cache包中的cache.decorators子包中等各個裝飾者的實現(xiàn);
二.SpringBoot整合(spring整合過程差不多裙犹,只不過是springboot自動的默認值變手動)
AutoConfiguration
1.spring.factory文件指定EnableAutoConfiguration為MybatisLanguageDriverAutoConfiguration(sql加載)和MybatisAutoConfiguration(這個是我們現(xiàn)在關注的)
2.MybatisAutoConfiguration類中定義了默認的SqlSessionFactory的bean和SqlSessionTemplate
3.這個類中會加載用戶配置和xml
MapperScan
1.@MapperScan注解導入MapperScannerRegistrar類尽狠,而MapperScannerRegistrar實現(xiàn)ImportBeanDefinitionRegistrar,在加載配置類的時候就會調用到registerBeanDefinitions方法
2.registerBeanDefinitions方法注冊MapperScannerConfigurer的bean定義叶圃,而且MapperScannerConfigurer實現(xiàn)BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法袄膏,在掃描配置類時會被調用
3.構造ClassPathMapperScanner,掃描配置的basePackage
4.ClassPathMapperScanner實現(xiàn)了ClassPathBeanDefinitionScanner掺冠,重寫isCandidateComponent哩陕,去判斷掃描的類是不是component(邏輯就是是不是接口)。
5.調用父類的(spring的)doScan方法赫舒,得到beanDefinitions
6.遍歷beanDefinitions,將BeanDefinition進行修改闽瓢,beanclass修改為MapperFactoryBean接癌,AutowireMode修改為byType
7.調用MapperFactoryBean的getObject方法(懶加載的),getSqlSession()去得到一個sqlSession對象扣讼,然后調用sqlSession的getMapper缺猛,生成一個代理對象(jdk動態(tài)代理),這樣就成為spring管理的bean了椭符。