我們大都選擇使用宣告式(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 來配置宣告式事務管理,是實際專案中最常使用的配置方式,因為它的表達能力最強而且使用也最為靈活 。