Spring給了一個約定(AOP開發也給了我們一個約定),如果使用的是聲明式事務,那么當你的業務方法不發生異常(或者發生異常,但該異常也被配置信息允許提交事務)時,Spring就會讓事務管理器提交事務,而發生異常(並且該異常不被你的配置信息所允許提交事務)時,則讓事務管理器回滾事務。
Transactional的配置項


<!--使用聲明式事務配置注解驅動-->
<tx:annotation-driven transaction-manager="transactionManager"/>
使用XML進行配置事務管理器
使用XML配置事務管理器的方法很多,但是也不常用,更多時我們會采用注解式的事務。為此筆者只介紹一種通用的XML聲明式事務配置,不過它卻在一定流程上揭露了事務管理器的內部實現。它需要一個事務攔截器——TransactionInterceptor,可以把攔截器想象成AOP編程。
代碼清單:配置事務攔截器
配置transactionAttributes的內容是需要關注的重點,Spring IoC啟動時會解析這些內容,放到事務定義類Transac-tionDefinition中,再運行時會根據正則式的匹配度決定方法采取哪種策略。顯然這使用了攔截器和Spring AOP的編程技術,這也揭示了聲明式事務的底層原理——Spring AOP技術。
還需要告訴Spring哪些類要使用事務攔截器進行攔截,為此我們再配置一個類BeanNameAutoProxyCreator
代碼清單:指明事務攔截器攔截哪些類
代碼清單:配置事務攔截器
<!--配置事務攔截器--> <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager"/> <!-- 配置事務屬性 --> <property name="transactionAttributes"> <props> <!-- key代表的是業務方法的正則式匹配 ,而其內容可以配置各類事務定義參數--> <prop key="insert*">PROPAGATION_REQUIRED,ISOLATION_READ_UNCOMMITTED</prop> <prop key="save*">PROPAGATION_REQUIRED,ISOLATION_READ_ UNCOMMITTED</prop> <prop key="add*">PROPAGATION_REQUIRED,ISOLATION_READ_ UNCOMMITTED</prop> <prop key="select*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="del*">PROPAGATION_REQUIRED,ISOLATION_READ_ UNCOMMITTED</prop> <prop key="remove*">PROPAGATION_REQUIRED,ISOLATION_READ_ UNCOMMITTED</prop> <prop key="update*">PROPAGATION_REQUIRED,ISOLATION_READ_ UNCOMMITTED</prop> </props> </property> </bean>
配置transactionAttributes的內容是需要關注的重點,Spring IoC啟動時會解析這些內容,放到事務定義類Transac-tionDefinition中,再運行時會根據正則式的匹配度決定方法采取哪種策略。顯然這使用了攔截器和Spring AOP的編程技術,這也揭示了聲明式事務的底層原理——Spring AOP技術。
還需要告訴Spring哪些類要使用事務攔截器進行攔截,為此我們再配置一個類BeanNameAutoProxyCreator
代碼清單:指明事務攔截器攔截哪些類
<!--指明事務攔截器攔截哪些類--> <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <list> <value>*ServiceImpl</value> </list> </property> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> </list> </property> </bean>
BeanName屬性告訴Spring如何攔截類。由於聲明為*ServiceImpl,所有關於Service是現實類都會被其攔截,然后interceptorNames則是定義事務攔截器,這樣對應的類和方法就會被事務管理器所攔截了。
聲明式事務的約定流程
首先Spring通過事務管理器(PlatformTransactionManager的子類)創建事務,與此同時會把事務定義中的隔離級別、超時時間等屬性根據配置內容往事務上設置。而根據傳播行為配置采取一種特定的策略,后面會談到傳播行為的使用問題,這是Spring根據配置完成的內容,你只需要配置,無須編碼。然后,啟動開發者提供的業務代碼,我們知道Spring會通過反射的方式調度開發者的業務代碼,但是反射的結果可能是正常返回或者產生異常返回,那么它給的約定是只要發生異常,並且符合事務定義類回滾條件的,Spring就會將數據庫事務回滾,否則將數據庫事務提交,這也是Spring自己完成的。你會驚奇地發現,在整個開發過程中,只需要編寫業務代碼和對事務屬性進行配置就可以了,並不需要使用代碼干預,工作量比較少,代碼邏輯也更為清晰,更有利於維護。

