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

deniro發表於2019-04-14

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

相關文章