spring事務管理器的源碼和理解

以前說了大多的原理,今天來說下spring的事務管理器的實現過程,順帶源碼乾貨帶上。

其實這個文章唯一的就是帶着看看代碼,但是前提你要懂得動態代理以及字節碼增強方面的知識(http://blog.csdn.net/xieyuooo/article/details/7624146),關於annotation在文章:http://blog.csdn.net/xieyuooo/article/details/8002321

也有說明,所以本文也就帶着看看代碼而已。

關於annotation這裏就不說了,我們看看平時一般會怎麼樣來配置spring的配置,通過配置文件反射源碼如何看看。

一般來講首先會配置一個datasource,至於你配置什麼連接池還是用JNDI這裏就不提到細節,總之我們認爲配置的spring的全局名稱爲dataSource就可以了。


接下來會將datasource交給各種連接池的操作類,如:ibatis、jdbcTemplate等等,這些不是我們關心的重點,我們需要關心的是dataSource是誰來管理了,在spring中配置了給一個DataSourceTransactionManager的對象:

 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource">
     <ref bean="dataSource" />
    </property>
</bean>

ok,先記錄下來,至於下面的NameMatchTransactionAttributeSource描述了那些情況要進行事務管理,我們將它理解爲一種屬性配置,在運行時需要解析即可,所以他也並不是我們特別需要的重點。


接下里看看:TransactionInterceptor,它看起來有點像攔截器了,他將transactionManager包裝進去了;

<bean id="txInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
  <property name="transactionManager">
    <ref bean="transactionManager"/>
  </property>
  <property name="transactionAttributeSource">
    <ref bean="txAttributes"/>
  </property>
</bean>

這裏是一個點,再繼續看,BeanNameAutoProxyCreator,這個看名字就知道是自動代理的類了,並且包裝了TransactionInterceptor的對象進去,也就是這個地方就是代理,然後會將事務的處理交給TransactionInterceptor攔截器來完成,可能這個不是我們的重點,不過簡單看看也無妨,這個類細節代碼就不貼了,進去你會看到就是講攔截器包裝後,然後通過beanName設置哪些類需要被攔截,根據你的配置來完成,spring 後來基於annotation實現的就不是這樣,他會掃描類中的annotation來實現類似的功能。

一起來簡單看看TransactionInterceptor吧:


細節代碼太多,看關鍵代碼,紅色部分表示出來了,其實在AOP調用中,我們比較關注invoke、intercept這類代碼關聯字的方法,因爲proxy調用的就是他們,由他們自己去調用其他的方法,這裏invoke首先發現在事務下,首先調用了createTranscationIfNecessary這個方法。


跟蹤進去看看:


這裏看到開始獲取TransactionManager了,get方法沒啥好看的,配置文件注入進去了,我們看看tm.getTranscation裏頭做了啥。

也就是跟蹤到你set的那個TranscationManager裏頭去了,PlatformTransactionManager有多個實現類,注意選擇自己實現的那部分:本程序中叫:DataSourceTransactionManager,跟蹤進去看看getTransaction方法

這個代理類,需要注意幾個加紅色的地方:

1、目前看來應該是獲事務的方法

2、部分如果發現事務對象獲取到就直接返回

3、做一個doBegin的操作,這i類關鍵字一般是指切入時的預先操作,那麼閒看看這個doBegin幹啥了


我們想要的東西來了,相信看到第二個紅色區域部分,大家都會很熟悉自己做事務是怎麼做的,發現spring也是這樣做的。

將connection做了一個setAutoCommit(false);非自動提交模式,接下來就要看如何和框架結合起來了,如何讓調用的時候使用到這個connection,調用方如何知道使用這個connection;

看另外兩個紅色的部分:

第一個紅色部分可以看出是獲取事務對象若爲空(不是事務或已經是事務),則從datasource對象中獲取一個connection,包裝成一個handle,放入事務對象中(事務對象內部的包裝請自己去看下)。

而第三個額部分是,如果是一個新的ConnectionHandler(其實判定的是一些狀態,使用中,spring會修改handler的狀態,這也是爲什麼spring要包裝一個handler了,因爲需要自定義的很多狀態信息);他執行了一個

TransactionSynchronizationManager.bindResource(getDatasource() , txObject.getConnectionHolder());

這樣一個操作,可見:TransactionSynchronizationManager提供了一個靜態方法getDatasource(),看名稱是綁定的意思,那麼綁定什麼呢?我們跟蹤進去看看:


咦,resouces貌似裏面有一個map,如果爲空,就put一個進去,那麼resouce是個什麼東西呢?他會不會有線程衝突的問題?

看看resouces是什麼:


ThreadLocal,對了,就是它了,有關ThreadLocal的原理和細節,我這不想多提,也不是這裏的重點,這裏明確的就是,雖然它是全局的一個靜態屬性,不過他是線程安全的,不論是get還是set還是remove。


我們知道這個connection被綁定到當前運行的線程中了,接下來只需要在使用時從這個裏面獲取出來即可。

我們再回到上面看到的doTransaction方法還沒看細節,這裏來看看。


可以看到,它果然是從這裏來獲取保存到當前線程的connection。


貌似看得差不多了,好像少了一半,那一半,datasouces是各個廠家的,他們的各自的datasouce方法是自己的,getConnection內部有自己的算法,如何做到他們在getConnection的時候,執行相應的,這個時候,我們來看看一個攔截connection的方式:TransactionAwareDataSourceProxy,

他內部有啥道理所在:


這裏可以看到使用了動態代理,獲取相應的datasouces,那麼就找到對應的代理類裏面去看看他的invoke方法是什麼:

TransactionAwareInvocationHandler裏面,可以跟蹤這個是一個內部類了,進去看看他的invoke方法:



可以看到切入的位置,向上看到兩個紅色部分是要去獲取connection,我們跟蹤進去看看:


接下來的就不用多說了吧,回到剛纔的代碼,不論是doGetConnection還是doReleaseConnection內部都會調用

TransactionSynchronizationManager.getResource(datasouce)

來獲取當前線程的connection。

當然各種連接操作對象也會有自己的transaction操作,他們也會去做setAutoCommit等相應的操作。不過最外層設置後,getConnection方法保證後,內部的操作幾乎就可以跳過了。


發佈了68 篇原創文章 · 獲贊 364 · 訪問量 75萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章