说说在 Spring 中,如何基于 XML 来配置事务

版权声明:如果喜欢,就点个赞呗 O(∩_∩)O~ https://blog.csdn.net/deniro_li/article/details/89296586

我们大都选择使用声明式(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 来配置声明式事务管理,是实际项目中最常使用的配置方式,因为它的表达能力最强而且使用也最为灵活 。

猜你喜欢

转载自blog.csdn.net/deniro_li/article/details/89296586