zoukankan      html  css  js  c++  java
  • Spring4笔记9--Spring的事务管理(AOP应用的例子)

    Spring的事务管理:

      事务原本是数据库中的概念,在 Dao 层。但一般情况下,需要将事务提升到业务层,即 Service 层。这样做是为了能够使用事务的特性来管理具体的业务。  
      在 Spring 中通常可以通过以下三种方式来实现对事务的管理:
        (1)使用 Spring 的事务代理工厂管理事务
        (2)使用 Spring 的事务注解管理事务
        (3)使用 AspectJ 的 AOP 配置管理事务

      Spring事务管理API:

        Spring 的事务管理,主要用到两个事务相关的接口。

        (1)事务管理器接口
            事务管理器是 PlatformTransactionManager 接口对象。其主要用于完成事务的提交、回滚,及获取事务的状态信息。查看 SpringAPI 帮助文档:Spring 框架解压目录下的docs/javadoc-api/index.html。

    Modifier and TypeMethod and Description
    void commit(TransactionStatus status)
    Commit the given transaction, with regard to its status.
    TransactionStatus getTransaction(TransactionDefinition definition)
    Return a currently active transaction or create a new one, according to the specified propagation behavior.
    void rollback(TransactionStatus status)
    Perform a rollback of the given transaction.

          A、常用的两个实现类
            PlatformTransactionManager 接口有两个常用的实现类:  
              DataSourceTransactionManager:使用 JDBC 或 iBatis  进行持久化数据时使用。  
              HibernateTransactionManager:使用 Hibernate 进行持久化数据时使用。
          B、Spring 的回滚方式
            Spring 事务的默认回滚方式是:发生运行时异常时回滚,发生受查异常时提交。不过,对于受查异常,程序员也可以手工设置其回滚方式

        (2)事务定义接口:
          事务定义接口 TransactionDefinition 中定义了事务描述相关的三类常量:事务隔离级别事务传播行为事务默认超时时限,及对它们的操作

          A、定义了五个事务隔离级别常量:
            这些常量均是以 ISOLATION_开头。即形如 ISOLATION_XXX。
              DEFAULT:采用DB默认的事务隔离级别。MySql的默认为REPEATABLE_READ;  Oracle默认为 READ_COMMITTED。
              READ_UNCOMMITTED:读未提交。未解决任何并发问题。
              READ_COMMITTED:读已提交。解决脏读,存在不可重复读与幻读。  
              REPEATABLE_READ:可重复读。解决脏读、不可重复读,存在幻读  
              SERIALIZABLE:串行化。不存在并发问题。

          B、定义了七个事务传播行为常量
            所谓事务传播行为是指,处于不同事务中的方法在相互调用时,执行期间事务的维护情况。如,A 事务中的方法 doSome()调用 B 事务中的方法 doOther(),在调用执行期间事务的维护情况,就称为事务传播行为。事务传播行为是加在方法上的。  
    事务传播行为常量都是以 PROPAGATION_  开头,形如 PROPAGATION_XXX。  
              REQUIRED:指定的方法必须在事务内执行。若当前存在事务,就加入到当前事务中;若当前没有事务,则创建一个新事务。这种传播行为是最常见的选择,也是Spring 默认的事务传播行为。  
              如该传播行为加在 doOther()方法上。若 doSome()方法在执行时就是在事务内的,则 doOther()方法的执行也加入到该事务内执行。若 doSome()方法没有在事务内执行,则 doOther()方法会创建一个事务,并在其中执行。

              SUPPORTS:指定的方法支持当前事务,但若当前没有事务,也可以以非事务方式执行。 

              MANDATORY:指定的方法必须在当前事务内执行,若当前没有事务,则直接抛出异常。

              REQUIRES_NEW:总是新建一个事务,若当前存在事务,就将当前事务挂起,直到新事务执行完毕。

              NOT_SUPPORTED:指定的方法不能在事务环境中执行,若当前存在事务,就将当前事务挂起。

              NEVER:指定的方法不能在事务环境下执行,若当前存在事务,就直接抛出异常。

              NESTED:指定的方法必须在事务内执行。若当前存在事务,则在嵌套事务内执行;若当前没有事务,则创建一个新事务。

          C、定义了默认事务超时时限
            常量 TIMEOUT_DEFAULT 定义了事务底层默认的超时时限,及不支持事务超时时限设置的 none 值。
            注意,事务的超时时限起作用的条件比较多,且超时的时间计算点较复杂。所以,该值一般就使用默认值即可。

      Spring事务代码详解:

        要求:实现模拟购买股票。存在两个实体:银行账户 Account 与股票账户 Stock。当要购买股票时,需要从 Account 中扣除相应金额的存款,然后在 Stock 中增加相应的股票数量。而在这个过程中,可能会抛出一个用户自定义的异常。异常的抛出,将会使两个操作回滚。

        Step1:创建数据库表 account、stock
        Step2:创建实体类 Account 与 Stock (略)
        Step3:定义 Dao 接口  IAccountDao 与 IStockDao

    1 package com.tongji.dao;
    2 
    3 public interface IAccountDao {
    4 
    5     void insertAccount(String aname, double money);
    6 
    7     void updateAccount(String aname, double money, boolean isBuy);
    8 
    9 }
    1 package com.tongji.dao;
    2 
    3 public interface IStockDao {
    4 
    5     void insertStock(String sname, int amount);
    6 
    7     void updateStock(String sname, int amount, boolean isBuy);
    8 
    9 }

        Step4:定义 Dao 实现类 AccountDaoImpl 与 StockDaoImpl

     1 package com.tongji.dao;
     2 
     3 import org.springframework.jdbc.core.support.JdbcDaoSupport;
     4 
     5 public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {
     6 
     7     @Override
     8     public void insertAccount(String aname, double money) {
     9         String sql = "insert into account(aname, balance) values(?,?)";
    10         this.getJdbcTemplate().update(sql, aname, money);
    11     }
    12 
    13     @Override
    14     public void updateAccount(String aname, double money, boolean isBuy) {
    15         String sql = "update account set balance=balance+? where aname=?";
    16         if (isBuy) {
    17             sql = "update account set balance=balance-? where aname=?";
    18         }
    19         this.getJdbcTemplate().update(sql, money, aname);
    20         
    21     }
    22 
    23 }
     1 package com.tongji.dao;
     2 
     3 import org.springframework.jdbc.core.support.JdbcDaoSupport;
     4 
     5 public class StockDaoImpl extends JdbcDaoSupport implements IStockDao {
     6 
     7     @Override
     8     public void insertStock(String sname, int amount) {
     9         String sql = "insert into stock(sname, count) values (?,?)";
    10         this.getJdbcTemplate().update(sql , sname, amount);
    11     }
    12 
    13     @Override
    14     public void updateStock(String sname, int amount, boolean isBuy) {
    15         //isBuy为true,则表示购买股票,此时应增加股票账户中的股票数量
    16         String sql = "update stock set count=count-? where sname=?";
    17         if (isBuy) {
    18             sql = "update stock set count=count+? where sname=?";
    19         }
    20         this.getJdbcTemplate().update(sql, amount, sname);
    21     }
    22 
    23 }

        Step5:定义异常类 StockException

     1 package com.tongji.beans;
     2 
     3 public class StockException extends Exception {
     4     private static final long serialVersionUID = 5377570098437361228L;
     5 
     6     public StockException() {
     7         super();
     8     }
     9 
    10     public StockException(String message) {
    11         super(message);
    12     }
    13     
    14 }

        Step6:定义 Service 接口 IStockProcessService

    1 package com.tongji.service;
    2 
    3 public interface IStockProcessService {
    4     void openAccount(String aname, double money);
    5     void openStock(String sname, int amount);
    6     void buyStock(String aname, double money, String sname, int amount);
    7 }

        Step7:定义 service 的实现类 StockProcessServiceImpl

     1 package com.tongji.service;
     2 
     3 import org.springframework.transaction.annotation.Isolation;
     4 import org.springframework.transaction.annotation.Propagation;
     5 import org.springframework.transaction.annotation.Transactional;
     6 
     7 import com.tongji.beans.StockException;
     8 import com.tongji.dao.IAccountDao;
     9 import com.tongji.dao.IStockDao;
    10 
    11 public class StockProcessServiceImpl implements IStockProcessService{
    12      private IAccountDao accountDao;
    13      private IStockDao stockDao;
    14     
    15     public void setAccountDao(IAccountDao accountDao) {
    16         this.accountDao = accountDao;
    17     }
    18 
    19     public void setStockDao(IStockDao stockDao) {
    20         this.stockDao = stockDao;
    21     }
    22 
    23     @Override
    24     public void openAccount(String aname, double money) {
    25         accountDao.insertAccount(aname, money);
    26     }
    27 
    28     @Override
    29     public void openStock(String sname, int amount) {
    30         stockDao.insertStock(sname, amount);
    31     }
    32 
    33     @Override
    34     public void buyStock(String aname, double money, String sname, int amount) throws StockException {
    35         boolean isBuy = true;
    36         accountDao.updateAccount(aname, money, isBuy);
    37         //故意抛出异常
    38         if (true) {
    39             throw new StockException("购买股票异常");
    40         }
    41         stockDao.updateStock(sname, amount, isBuy);
    42     }
    43 
    44 }

        Step8:定义Spring 配置文件 

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
     5         http://www.springframework.org/schema/beans 
     6         http://www.springframework.org/schema/beans/spring-beans.xsd
     7         http://www.springframework.org/schema/context 
     8         http://www.springframework.org/schema/context/spring-context.xsd">
     9     
    10     <!-- 注册数据源:C3P0数据源 -->
    11     <bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    12         <property name="driverClass" value="${jdbc.driverClass}" />
    13         <property name="jdbcUrl" value="${jdbc.url}" />
    14         <property name="user" value="${jdbc.user}" />
    15         <property name="password" value="${jdbc.password}" />
    16     </bean>
    17     
    18     <!-- 注册JDBC属性文件 -->
    19     <context:property-placeholder location="classpath:jdbc.properties"/>
    20     
    21     <!-- 注册Dao -->
    22     <bean id="accountDao" class="com.tongji.dao.AccountDaoImpl">
    23         <property name="dataSource" ref="myDataSource"/>
    24     </bean>
    25     <bean id="stockDao" class="com.tongji.dao.StockDaoImpl">
    26         <property name="dataSource" ref="myDataSource"/>
    27     </bean>
    28     <!-- 注册Service -->
    29     <bean id="stockService" class="com.tongji.service.StockProcessServiceImpl">
    30         <property name="accountDao" ref="accountDao"/>
    31         <property name="stockDao" ref="stockDao"/>
    32     </bean>    
    33 </beans>

        Step9:测试类

     1 package com.tongji.test;
     2 
     3 import org.junit.Before;
     4 import org.junit.Test;
     5 import org.springframework.context.ApplicationContext;
     6 import org.springframework.context.support.ClassPathXmlApplicationContext;
     7 
     8 import com.tongji.service.IStockProcessService;
     9 
    10 public class MyTest {
    11     
    12     private IStockProcessService service;
    13 
    14     @Before
    15     public void before() {
    16         //创建容器
    17         @SuppressWarnings("resource")
    18         ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    19         service = (IStockProcessService) ac.getBean("stockService");
    20     }
    21     
    22     @Test
    23     public void testOpen() {
    24         service.openAccount("张三", 10000);
    25         service.openStock("华为", 5);
    26     }
    27     
    28     @Test
    29     public void testBuyStock() {
    30         service.buyStock("张三", 2000, "华为", 5);
    31     }
    32     
    33 }

        此配置文件没有采用事务管理,所以购买股票的时候,出现了数据库中账户金额减少了,但是股票数目没有增加的不一致情况。

      

      使用 Spring 的事务代理工厂管理事务:

        该方式是,需要为目标类,即 Service 的实现类创建事务代理。事务代理使用的类是TransactionProxyFactoryBean,该类需要初始化如下一些属性:
          (1)transactionManager:事务管理器
          (2)target:目标对象,即 Service 实现类对象
          (3)transactionAttributes:事务属性设置
          对于 XML 配置代理方式实现事务管理时,受查异常的回滚方式,程序员可以通过以下方式进行设置:通过“-异常”方式,可使发生指定的异常时事务回滚;通过“+异常”方式,可使发生指定的异常时事务提交。

        修改Spring配置文件:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
     5         http://www.springframework.org/schema/beans 
     6         http://www.springframework.org/schema/beans/spring-beans.xsd
     7         http://www.springframework.org/schema/context 
     8         http://www.springframework.org/schema/context/spring-context.xsd">
     9     
    10     <!-- 注册数据源:C3P0数据源 -->
    11     <bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    12         <property name="driverClass" value="${jdbc.driverClass}" />
    13         <property name="jdbcUrl" value="${jdbc.url}" />
    14         <property name="user" value="${jdbc.user}" />
    15         <property name="password" value="${jdbc.password}" />
    16     </bean>
    17     
    18     <!-- 注册JDBC属性文件 -->
    19     <context:property-placeholder location="classpath:jdbc.properties"/>
    20     
    21     <!-- 注册Dao -->
    22     <bean id="accountDao" class="com.tongji.dao.AccountDaoImpl">
    23         <property name="dataSource" ref="myDataSource"/>
    24     </bean>
    25     <bean id="stockDao" class="com.tongji.dao.StockDaoImpl">
    26         <property name="dataSource" ref="myDataSource"/>
    27     </bean>
    28     <!-- 注册Service -->
    29     <bean id="stockService" class="com.tongji.service.StockProcessServiceImpl">
    30         <property name="accountDao" ref="accountDao"/>
    31         <property name="stockDao" ref="stockDao"/>
    32     </bean>    
    33     
    34     <!-- 事务 -->
    35     <!-- 注册事务管理器 -->
    36     <bean id="myTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    37         <property name="dataSource" ref="myDataSource"/>
    38     </bean>
    39     <!-- 生成事务代理 -->
    40     <bean id="stockServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    41         <property name="transactionManager" ref="myTxManager"/>
    42         <property name="target" ref="stockService"/>
    43         <property name="transactionAttributes">
    44             <props>
    45                 <prop key="open*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>
    46                 <prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-StockException</prop>
    47             </props>
    48         </property>
    49     </bean>
    50 </beans>

        由于本项目使用的是 JDBC 进行持久化,所以使用 DataSourceTransactionManager 类作为事务管理器。

        修改测试类:

         public void before() {
               //创建容器
               @SuppressWarnings("resource")
               ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
               service = (IStockProcessService) ac.getBean("stockServiceProxy");
           }

      使用 Spring 的事务注解管理事务:
        通过@Transactional 注解方式,也可将事务织入到相应方法中。而使用注解方式,只需在配置文件中加入一个 tx 标签,以告诉 spring 使用注解来完成事务的织入。该标签只需指定一个属性,事务管理器。

        修改Spring配置文件:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4         xmlns:context="http://www.springframework.org/schema/context"
     5         xmlns:aop="http://www.springframework.org/schema/aop"
     6         xmlns:tx="http://www.springframework.org/schema/tx" 
     7         xsi:schemaLocation="
     8         http://www.springframework.org/schema/beans 
     9         http://www.springframework.org/schema/beans/spring-beans.xsd
    10         http://www.springframework.org/schema/context 
    11         http://www.springframework.org/schema/context/spring-context.xsd
    12         http://www.springframework.org/schema/tx 
    13         http://www.springframework.org/schema/tx/spring-tx.xsd
    14         http://www.springframework.org/schema/aop 
    15         http://www.springframework.org/schema/aop/spring-aop.xsd">
    16     
    17     <!-- 注册数据源:C3P0数据源 -->
    18     <bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    19         <property name="driverClass" value="${jdbc.driverClass}" />
    20         <property name="jdbcUrl" value="${jdbc.url}" />
    21         <property name="user" value="${jdbc.user}" />
    22         <property name="password" value="${jdbc.password}" />
    23     </bean>
    24     
    25     <!-- 注册JDBC属性文件 -->
    26     <context:property-placeholder location="classpath:jdbc.properties"/>
    27     
    28     <!-- 注册Dao -->
    29     <bean id="accountDao" class="com.tongji.dao.AccountDaoImpl">
    30         <property name="dataSource" ref="myDataSource"/>
    31     </bean>
    32     <bean id="stockDao" class="com.tongji.dao.StockDaoImpl">
    33         <property name="dataSource" ref="myDataSource"/>
    34     </bean>
    35     <!-- 注册Service -->
    36     <bean id="stockService" class="com.tongji.service.StockProcessServiceImpl">
    37         <property name="accountDao" ref="accountDao"/>
    38         <property name="stockDao" ref="stockDao"/>
    39     </bean>    
    40     
    41     <!-- 事务 -->
    42     <!-- 注册事务管理器 -->
    43     <bean id="myTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    44         <property name="dataSource" ref="myDataSource"/>
    45     </bean>
    46     <!-- 开启注解驱动 -->
    47     <tx:annotation-driven transaction-manager="myTxManager"/>
    48 </beans>

        修改 service 的实现类 StockProcessServiceImpl:

     1 package com.tongji.service;
     2 
     3 import org.springframework.transaction.annotation.Isolation;
     4 import org.springframework.transaction.annotation.Propagation;
     5 import org.springframework.transaction.annotation.Transactional;
     6 
     7 import com.tongji.beans.StockException;
     8 import com.tongji.dao.IAccountDao;
     9 import com.tongji.dao.IStockDao;
    10 
    11 public class StockProcessServiceImpl implements IStockProcessService{
    12      private IAccountDao accountDao;
    13      private IStockDao stockDao;
    14     
    15     public void setAccountDao(IAccountDao accountDao) {
    16         this.accountDao = accountDao;
    17     }
    18 
    19     public void setStockDao(IStockDao stockDao) {
    20         this.stockDao = stockDao;
    21     }
    22 
    23     @Override
    24     @Transactional(isolation=Isolation.DEFAULT, propagation=Propagation.REQUIRED)
    25     public void openAccount(String aname, double money) {
    26         accountDao.insertAccount(aname, money);
    27     }
    28 
    29     @Override
    30     @Transactional(isolation=Isolation.DEFAULT, propagation=Propagation.REQUIRED)
    31     public void openStock(String sname, int amount) {
    32         stockDao.insertStock(sname, amount);
    33     }
    34 
    35     @Override
    36     @Transactional(isolation=Isolation.DEFAULT, propagation=Propagation.REQUIRED, rollbackFor=StockException.class)
    37     public void buyStock(String aname, double money, String sname, int amount) throws StockException {
    38         boolean isBuy = true;
    39         accountDao.updateAccount(aname, money, isBuy);
    40         if (true) {
    41             throw new StockException("购买股票异常");
    42         }
    43         stockDao.updateStock(sname, amount, isBuy);
    44     }
    45 
    46 }

        @Transactional 的所有可选属性如下所示:
          propagation:用于设置事务传播属性。该属性类型为 Propagation 枚举,默认值为Propagation.REQUIRED。
          isolation:用于设置事务的隔离级别。该属性类型为 Isolation 枚举,默认值为Isolation.DEFAULT。
          readOnly:用于设置该方法对数据库的操作是否是只读的。该属性为 boolean,默认值为 false。
          timeout:用于设置本操作与数据库连接的超时时限。单位为秒,类型为 int,默认值为-1,即没有时限。
          rollbackFor:指定需要回滚的异常类。类型为 Class[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组。
          rollbackForClassName:指定需要回滚的异常类类名。类型为 String[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组。
          noRollbackFor:指定不需要回滚的异常类。类型为 Class[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组。
          noRollbackForClassName:指定不需要回滚的异常类类名。类型为 String[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组。
         需要注意的是,@Transactional 若用在方法上,只能用于 public 方法上。对于其他非public 方法,如果加上了注解@Transactional,虽然 Spring 不会报错,但不会将指定事务织入到该方法中。因为 Spring 会忽略掉所有非 public 方法上的@Transaction 注解。  
        若@Transaction 注解在类上,则表示该类上所有的方法均将在执行时织入事务。

      使用 AspectJ 的 AOP 配置管理事务(重点):

        使用 XML 配置事务代理的方式的不足是,每个目标类都需要配置事务代理。当目标类较多,配置文件会变得非常臃肿。使用 XML 配置顾问方式可以自动为每个符合切入点表达式的类生成事务代理。

        修改Spring配置文件:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4         xmlns:context="http://www.springframework.org/schema/context"
     5         xmlns:aop="http://www.springframework.org/schema/aop"
     6         xmlns:tx="http://www.springframework.org/schema/tx" 
     7         xsi:schemaLocation="
     8         http://www.springframework.org/schema/beans 
     9         http://www.springframework.org/schema/beans/spring-beans.xsd
    10         http://www.springframework.org/schema/context 
    11         http://www.springframework.org/schema/context/spring-context.xsd
    12         http://www.springframework.org/schema/tx 
    13         http://www.springframework.org/schema/tx/spring-tx.xsd
    14         http://www.springframework.org/schema/aop 
    15         http://www.springframework.org/schema/aop/spring-aop.xsd">
    16     
    17     <!-- 注册数据源:C3P0数据源 -->
    18     <bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    19         <property name="driverClass" value="${jdbc.driverClass}" />
    20         <property name="jdbcUrl" value="${jdbc.url}" />
    21         <property name="user" value="${jdbc.user}" />
    22         <property name="password" value="${jdbc.password}" />
    23     </bean>
    24     
    25     <!-- 注册JDBC属性文件 -->
    26     <context:property-placeholder location="classpath:jdbc.properties"/>
    27     
    28     <!-- 注册Dao -->
    29     <bean id="accountDao" class="com.tongji.dao.AccountDaoImpl">
    30         <property name="dataSource" ref="myDataSource"/>
    31     </bean>
    32     <bean id="stockDao" class="com.tongji.dao.StockDaoImpl">
    33         <property name="dataSource" ref="myDataSource"/>
    34     </bean>
    35     <!-- 注册Service -->
    36     <bean id="stockService" class="com.tongji.service.StockProcessServiceImpl">
    37         <property name="accountDao" ref="accountDao"/>
    38         <property name="stockDao" ref="stockDao"/>
    39     </bean>    
    40     
    41     <!-- 事务 -->
    42     <!-- 注册事务管理器 -->
    43     <bean id="myTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    44         <property name="dataSource" ref="myDataSource"/>
    45     </bean>
    46     <!-- 注册事务通知 -->
    47     <tx:advice id="txAdvice" transaction-manager="myTxManager">
    48         <tx:attributes>
    49             <!-- 指定在连接点方法上应用的事务属性 -->
    50             <tx:method name="open*" isolation="DEFAULT" propagation="REQUIRED"/>
    51             <tx:method name="buyStock" isolation="DEFAULT" propagation="REQUIRED" rollback-for="StockException"/>
    52         </tx:attributes>
    53     </tx:advice>
    54     
    55     <!-- AOP配置 -->
    56     <aop:config>
    57         <!-- 指定切入点 -->
    58         <aop:pointcut expression="execution(* *..service.*.*(..))" id="stockPointCut"/>
    59         <aop:advisor advice-ref="txAdvice" pointcut-ref="stockPointCut"/>
    60     </aop:config>
    61 </beans>

      总结:Spring 的事务管理,是 AOP 的应用,将事务作为切面织入到了 Service 层的业务方法中。

  • 相关阅读:
    命令提示符窗口adb shell 执行sqlite命令时进入 ...> 状态如何退出
    通过android studio 浏览模拟器中文件
    vim快捷键参考
    快速体验openstack-用devstack安装openstack
    css靠左,靠右
    全国-城市-百度地图中心点坐标
    java_dom4j解析xml
    December 31st, Week 53rd Tuesday, 2019
    December 28th, Week 52nd Saturday, 2019
    December 21st, Week 51st Saturday, 2019
  • 原文地址:https://www.cnblogs.com/qjjazry/p/6366204.html
Copyright © 2011-2022 走看看