說說在 Spring 中,如何基於 XML 來配置事務

我們大都選擇使用宣告式(XML 或者註解)來配置事務,因為這種方式對程式碼的侵入最小。特別是 XML 方式的配置,可以讓事務管理配置資訊從業務程式碼中完全移除。
Spring 的宣告式事務管理是通過 AOP 實現的。 Spring 會讀取事務的宣告配置,將事務管理的增強邏輯,動態織入到業務方法的相應連線點中 。
Spring 2.0 之後引入了 AspectJ 切面定義語言,所以我們可以基於 aop/tx 名稱空間來配置事務。
假設有這樣的一個 UserService 類:
@Service public class UserService { @Autowired private UserDao userDao; /** * 新增 * * @param user */ public int addUser(final User user) { return userDao.save(user); } /** * 依據 Id,獲取賬號 * * @param userId * @return */ public User getUser(Long userId) { return userDao.get(userId); } /** * 更新賬號所對應的密碼 *@param userId * @param pwd */ public int update(Long userId, String pwd) { return userDao.update(userId, pwd); } }
希望讓 get***() 方法擁有隻讀事務,其它方法擁有寫事務。對這一業務要求,我們可以使用 aop/tx 名稱空間來配置。
spring_tx.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd "> <!-- 掃描包含註解定義的類包--> <context:component-scan base-package="net.deniro.xxx.transaction.xml"/> <!-- 資料來源--> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://127.0.0.1:3306/spring4" p:username="root" p:password="xxx"/> <!-- JDBC 模板--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref="dataSource" /> <!-- 事務管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource"/> <!-- 增強事務--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="get*" read-only="false"/> <tx:method name="add*" rollback-for="Exception"/> <tx:method name="update"/> </tx:attributes> </tx:advice> <!-- 定義需要增強的目標方法--> <aop:config> <!-- 增強切面--> <aop:pointcut id="serviceMethod" expression="exec。ution(* net.deniro.xxx.transaction.xml.UserService.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod"/> </aop:config> </beans>
在 aop 名稱空間中,通過切點表示式,將 net.deniro.xxx.transaction.xml.UserService 中的所有方法,都納入了事務增強的管理範圍。
其中,最關鍵的是 <tx:method>
元素,它擁有如下屬性:
屬性 | 是否必須 | 預設值 | 說明 |
---|---|---|---|
name | 必須 | 相關聯的方法名。可以使用萬用字元(*)。 | 形如:get 、add 等。 |
propagation | - | REQUIRED | 事務傳播行為,可選值為:REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED |
isolation | - | DEFAULT | 事務隔離級別,可選值為:DEFAULT、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE |
timeout | - | -1 | 事務超時時間(單位為 s)。如果為 -1,則事務的超時時間由底層事務系統決定。 |
read-only | - | false | 是否只讀 |
rollback-for | - | 所有執行期異常,都回滾 | 觸發事務回滾的 Excepiton 名稱,多個以逗號隔開。 |
norollback-for | 所有檢查型異常,都不回滾 | 不觸發事務回滾的 Excepiton 名稱,多個以逗號隔開。 |
基於 aop/tx 來配置宣告式事務管理,是實際專案中最常使用的配置方式,因為它的表達能力最強而且使用也最為靈活 。