Mybatis 源碼-異常
異常模塊結(jié)構(gòu)
包結(jié)構(gòu)
異常類繼承樹
IbatisException 類是頂層類历涝,但是已經(jīng)被加上 @Deprecated
涮阔,說明廢棄掉了而 PersistenceException 類則是 IbatisException 的繼承者稽莉,其他的異常類都只是用于業(yè)務(wù)區(qū)分邀跃,大同小異
異常工廠 ExceptionFactory
職責(zé):把普通異常包裝成mybatis自己的PersistenceException
使用例子
ErrorContext
正如其名处硬,ErrorContext 記錄本次執(zhí)行過程的相關(guān)上下文信息小槐,待發(fā)生異常的時(shí)候,其他組件就可以從本類實(shí)例中獲取到相關(guān)上下文
內(nèi)部結(jié)構(gòu)
其內(nèi)部維護(hù)了一個(gè) ThreadLocal
和 6 個(gè)存儲(chǔ)異常信息的成員變量來存儲(chǔ)當(dāng)前執(zhí)行SQL的線程的信息
這些異常信息歸結(jié)起來就是:誰荷辕,在哪個(gè)文件凿跳,做什么,執(zhí)行什么SQL疮方,而產(chǎn)生異常
resource:異常所處資源文件
activity:觸發(fā)異常的操作
object:觸發(fā)異常的對(duì)象
message:異常信息的概況
sql:產(chǎn)生異常的SQL
cause:詳細(xì)的Java異常日志
另外 ErrorContext 提供了一個(gè)一次性打印所有異常信息的 toString() 方法
對(duì)照異常打印的信息
rest() 方法
既然使用了 ThreadLocal 那么必然需要在用完的時(shí)候清空掉它控嗜,Mybatis會(huì)在每次操作后使用 try-catch-finally 機(jī)制來確保ThreadLocal 被重置
這個(gè)方法主要在以下三個(gè)類中調(diào)用
DefaultSqlSession
DefaultSqlSessionFactory
SqlSessionFactoryBuilder
store() 和 recall()
store() 用于將當(dāng)前 ErrorContext 存儲(chǔ)到 stored,然后 new 一個(gè)新的 ErrorContext 到 ThreadLocal
recall() 用于從當(dāng)前 ErrorContext 的 stored 取出之前存的 ErrorContext 然后放入 ThreadLocal
這兩個(gè)方法只在一處地方調(diào)用:BaseStatementHandler
TODO:這兩個(gè)方法的具體用處骡显,待探究
總結(jié)
Mybatis 通過將所有業(yè)務(wù)異常類繼承到 PersistenceException 下疆栏,再通過 ExceptionFactory 異常工廠類來統(tǒng)一生產(chǎn)異常信息。
這么多異常類惫谤,如果各自的業(yè)務(wù)自己拋出壁顶,那么勢(shì)必會(huì)導(dǎo)致日志亂序不容易查看。作者的做法很聰明溜歪,在 ErrorContext 中維護(hù)一個(gè)ThreadLocal 和 6 個(gè)異常的關(guān)鍵信息私有成員變量若专,然后對(duì)外提供鏈?zhǔn)骄幊痰?set 方法,以及一個(gè)可以直接打印所有異常信息的 toString()方法蝴猪,從而把當(dāng)前線程所執(zhí)行SQL過程的異常信息调衰,歸集并打印膊爪,日志內(nèi)容簡單明了,幫助開發(fā)者可以很快速的定位問題的產(chǎn)生窖式。