Spring中的AOP进行事务管理有三种方式

A.自定义事务切面

   利用AspectJ来编写事务,我们一般把这个切面作用在service层中。其他代码在下面

    编写一个Transaction实现类,通过Spring容器进行管理

  Transaction.java

  1. package com.niit.aspect;
  2.  
  3. import javax.sql.DataSource;
  4.  
  5. import org.aspectj.lang.ProceedingJoinPoint;
  6. import org.aspectj.lang.annotation.AfterThrowing;
  7. import org.aspectj.lang.annotation.Around;
  8. import org.aspectj.lang.annotation.Aspect;
  9. import org.aspectj.lang.annotation.Pointcut;
  10. import org.springframework.jdbc.datasource.DataSourceTransactionManager;
  11. import org.springframework.transaction.TransactionDefinition;
  12. import org.springframework.transaction.TransactionStatus;
  13. import org.springframework.transaction.support.DefaultTransactionDefinition;
  14.  
  15. /**
  16. * 文件名称: com.niit.aspect.TransactionAspect.java</br>
  17. * 初始作者: Administrator</br>
  18. * 创建日期: 2018-2-5</br>
  19. * 功能说明: 事务切面类<br/>
  20. * =================================================<br/>
  21. * 修改记录:<br/>
  22. * 修改作者 日期 修改内容<br/>
  23. * ================================================<br/>
  24. * Copyright (c) 2010-2011 .All rights reserved.<br/>
  25. */
  26. // @Aspect注解的作用是使得当前的类成为一个切面类
  27. @Aspect
  28. public class TransactionAspect {
  29.  
  30. private DataSource ds;
  31. private DataSourceTransactionManager manager;
  32. private TransactionStatus status;
  33.  
  34. /**
  35. * 方法名随意
  36. */
  37. // execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)throws-pattern?)
  38. // 拦截com.niit.service包及其子包下所有类中的public声明的任意方法
  39. @Pointcut("execution(public * com.niit.service.*.*(..))")
  40. public void method() {
  41.  
  42. // 该方法的作用仅仅是为了在上面加上一个@Pointcut注解来说明当前的切入点
  43. // 方法中不需要加任何的代码逻辑
  44. }
  45.  
  46. /**
  47. * 这个方法相当于MethodInterceptor中的invoke方法,实现的是一个环绕通知
  48. * 方法名随意
  49. *
  50. * @throws Throwable
  51. */
  52. // @Around:使得当前的方法成为一个环绕通知方法
  53. // method():就是前面定义切入点的这个方法名
  54. // ProceedingJoinPoint对象中封装了被调用的目标方法中的一些信息,也可以用来调用目标方法
  55. @Around(value = "method()")
  56. public Object doAroundTask(ProceedingJoinPoint pjp) throws Throwable {
  57.  
  58. System.out.println("环绕通知的前置部分...");
  59. // 定义事务对象
  60. DefaultTransactionDefinition def = new DefaultTransactionDefinition();
  61. // 设置事务的隔离级别--在一个事务中只能读取到另外一个事务已经提交的数据
  62. def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
  63. // 设置事务的传播方式--当需要事务的时候就主动创建使用事务
  64. def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
  65. // def.setReadOnly(true);
  66.  
  67. // 数据源事务管理器--对数据源中产生的连接对象进行统一管理
  68. // 参数为数据源对象
  69. manager = new DataSourceTransactionManager(ds);
  70. // 事务的状态--事务的提交或回滚等操作都是围绕这个事务状态展开的
  71. status = manager.getTransaction(def);
  72. Object result = null;
  73. result = pjp.proceed(pjp.getArgs());
  74. System.out.println("环绕通知的后置部分...");
  75. // 提交事务
  76. manager.commit(status);
  77. return result;
  78. }
  79.  
  80. // 在目标方法执行中抛出异常时执行的切面--异常通知
  81. // pointcut:异常通知的切入点,写法同环绕通知中的写法
  82. // throwing后面的字符串和方法中的参数名是相同的,可以使用这个名字在异常通知的方法中打印和获得目标方法执行过程中相关的异常信息
  83. @AfterThrowing(pointcut = "method()", throwing = "ex")
  84. public void doAfterThrow(Exception ex) {
  85.  
  86. System.out.println("发生了异常...");
  87. System.out.println(ex.getMessage());
  88. // 遇到异常--回滚事务
  89. manager.rollback(status);
  90. }
  91.  
  92. public DataSource getDs() {
  93.  
  94. return ds;
  95. }
  96.  
  97. public void setDs(DataSource ds) {
  98.  
  99. this.ds = ds;
  100. }
  101.  
  102. public DataSourceTransactionManager getManager() {
  103.  
  104. return manager;
  105. }
  106.  
  107. public void setManager(DataSourceTransactionManager manager) {
  108.  
  109. this.manager = manager;
  110. }
  111.  
  112. public TransactionStatus getStatus() {
  113.  
  114. return status;
  115. }
  116.  
  117. public void setStatus(TransactionStatus status) {
  118.  
  119. this.status = status;
  120. }
  121.  
  122. }

  

  使用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:jdbc="http://www.springframework.org/schema/jdbc"
  6. xmlns:jee="http://www.springframework.org/schema/jee"
  7. xmlns:tx="http://www.springframework.org/schema/tx"
  8. xmlns:aop="http://www.springframework.org/schema/aop"
  9. xmlns:mvc="http://www.springframework.org/schema/mvc"
  10. xmlns:util="http://www.springframework.org/schema/util"
  11. xmlns:jpa="http://www.springframework.org/schema/data/jpa"
  12. xsi:schemaLocation="
  13. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
  14. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
  15. http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
  16. http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
  17. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
  18. http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
  19. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
  20. http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
  21. http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
  22.  
  23. <!-- 通过util方式来读取properties配置文件 -->
  24. <util:properties id="dbConfig" location="classpath:jdbc.properties"/>
  25.  
  26. <!-- 定义dbcp数据源 -->
  27. <bean id="ds" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource">
  28. <property name="driverClassName" value="#{dbConfig.driver}"></property>
  29. <property name="url" value="#{dbConfig.url}"></property>
  30. <property name="username" value="#{dbConfig.username}"></property>
  31. <property name="password" value="#{dbConfig.userpwd}"></property>
  32. </bean>
  33.  
  34. <!-- Spring JDBC相关对象 -->
  35. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  36. <property name="dataSource" ref="ds"></property>
  37. </bean>
  38. <bean id="namedJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
  39. <constructor-arg index="0" ref="ds"></constructor-arg>
  40. </bean>
  41.  
  42. <!--
            开启AspectJ的自动代理
  43. 当Spring容器在初始化时,会通过@Aspect注解找到切面类,
  44. 再根据 <aop:aspectj-autoproxy/>配置,将切面自动作用到目标方法上
  45. -->
  46. <aop:aspectj-autoproxy/>
  47. <!-- AspectJ事务管理切面 -->
  48. <bean id="txAspect" class="com.stu.aspect.TransactionAspect">
  49. <property name="ds" ref="ds"></property>
  50. </bean>
  51.  
  52. <bean id="bankDao" class="com.stu.dao.impl.BankDaoImpl">
  53. <property name="jdbcTempalte" ref="jdbcTemplate"></property>
  54. </bean>
  55. <bean id="bankService" class="com.niit.service.impl.BankServiceImpl">
  56. <property name="bankDao" ref="bankDao"></property>
  57. </bean>
  58.  
  59. </beans>

 

B,Transaction注解

    利用AspectJ来编写事务,用银行的转账来进行模拟。

    当一个用户从自己的账号转出金额到另一个用户账户上,两个账户的金额都应该有变化,有一个失败则全部失败。先建立Bank有关的Dao和Service层,以及对应的实现层。TransactionAspect为事务类

    

1.写一个类,充当为事务切面类,一般对于事务的管理,选择放在Service层中。添加了@Transaction注解

    TransactionAspect.java

  1. package com.stu.aspect;
  2.  
  3. import javax.sql.DataSource;
  4.  
  5. import org.aspectj.lang.ProceedingJoinPoint;
  6. import org.aspectj.lang.annotation.AfterThrowing;
  7. import org.aspectj.lang.annotation.Around;
  8. import org.aspectj.lang.annotation.Aspect;
  9. import org.aspectj.lang.annotation.Pointcut;
  10. import org.springframework.jdbc.datasource.DataSourceTransactionManager;
  11. import org.springframework.transaction.TransactionDefinition;
  12. import org.springframework.transaction.TransactionStatus;
  13. import org.springframework.transaction.support.DefaultTransactionDefinition;
  14.  
  15. /**
  16. * 文件名称: com.stu.aspect.TransactionAspect.java<br/>
  17. * 初始作者: Administrator<br/>
  18. * 创建日期: 2018-2-5<br/>
  19. * 功能说明: 事务切面类 <br/>
  20. * =================================================<br/>
  21. * 修改记录:<br/>
  22. * 修改作者 日期 修改内容<br/>
  23. * ================================================<br/>
  24. * Copyright (c) 2010-2011 .All rights reserved.<br/>
  25. */
  26. // 1.加上@Aspect注解,表示这个类是一个切面类
  27. @Aspect
  28. public class TransactionAspect {
  29.  
  30. /**
  31. * 定义为全局的私有属性,方便共享
  32. */
  33. private DataSource ds;
  34. private DataSourceTransactionManager manager;
  35. private TransactionStatus status;
  36.  
  37. /**
  38. * 2.写一个方法,加上@Pointcut注解表示为切入点,并且配置@Pointcut中的其他参数:
  39. *
  40. * @Pointcut(execution(modifiers-pattern? ret-type-pattern
  41. * declaring-type-pattern?name-pattern(param-pattern)throws-pattern?))<br />
  42. * execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)
  43. */
  44. @Pointcut("execution(public * com.stu.service.*.*(..))")
  45. public void method() {
  46.  
  47. // 该方法的作用仅仅是为了在上面加上一个@Pointcut注解来说明当前的切入点
  48. // 方法中不需要加任何的代码逻辑
  49. }
  50.  
  51. /**
  52. * 3.添加一个环绕通知,使用@Around注解。配置切入点方法,value为刚刚定义的切入点方法名称
  53. * 这个方法相当于MethodInterceptor中的invoke方法,实现的是一个环绕通知
  54. *
  55. * @throws Throwable
  56. */
  57. @Around(value = "method()")
  58. public Object doAroundTest(ProceedingJoinPoint pjp) throws Throwable {
  59.  
  60. System.out.println("---TransactionAspect.doAroundTest()---前置通知---");
  61. /**
  62. * 4.定义事务对象并设置事务的隔离级别和传播方式
  63. */
  64. DefaultTransactionDefinition def = new DefaultTransactionDefinition();
  65. // 隔离级别
  66. def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
  67. // 传播方式
  68. def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
  69.  
  70. /**
  71. * 5.数据源事务管理器--对数据源中产生的连接对象进行统一管理
  72. */
  73. manager = new DataSourceTransactionManager(ds);
  74. // 事务的状态,事务的提交或回滚操作都是围绕这个事务状态展开的
  75. status = manager.getTransaction(def);
  76. Object result = null;
  77. result = pjp.proceed(pjp.getArgs());
  78. System.out.println("---doAroundTest()---后置通知---");
  79. /**
  80. * 6. 提交
  81. */
  82. manager.commit(status);
  83.  
  84. return result;
  85. }
  86.  
  87. /**
  88. *7.使用@AfterThrowing注解添加一个在目标执行中抛出异常执行的切面--异常通知
  89. *pointcut:异常通知的切入点
  90. *throwing:后面的字符串和方法中的参数名是相同的,使用这个名字在异常通知中打印目标的异常信息
  91. */
  92. @AfterThrowing(pointcut = "method()", throwing = "ex")
  93. public void doAfterThorw(Exception ex) {
  94.  
  95. System.out.println("发生了异常");
  96. System.out.println(ex.getMessage());
  97. /**
  98. * 8.如果发生异常则进行回滚操作
  99. */
  100. manager.rollback(status);
  101. }
  102.  
  103. public DataSource getDs() {
  104.  
  105. return ds;
  106. }
  107.  
  108. public void setDs(DataSource ds) {
  109.  
  110. this.ds = ds;
  111. }
  112.  
  113. public DataSourceTransactionManager getManager() {
  114.  
  115. return manager;
  116. }
  117.  
  118. public void setManager(DataSourceTransactionManager manager) {
  119.  
  120. this.manager = manager;
  121. }
  122.  
  123. public TransactionStatus getStatus() {
  124.  
  125. return status;
  126. }
  127.  
  128. public void setStatus(TransactionStatus status) {
  129.  
  130. this.status = status;
  131. }
  132.  
  133. }

 

@Pointcut注解的方法就是切入点,

  1. //@Pointcut(execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)throws-pattern?))
  2. //execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)
    @Pointcut("execution(public * com.stu.service.*.*(..))")
execution() 表达式的主体
第一个“*”符号 表示返回值的类型任意
  1. com.stu.service
AOP所切的服务的包名,即,需要进行横切的业务类
包名后面的“.*” 表示当前包及子包
第二个“.*” 表示类名,*即所有类
.*(..) 表示任何方法名,括号表示参数,两个点表示任何参数类型

2.补充完业务和dao层中的所有逻辑

  BankDao.java

  1. package com.stu.dao;
  2.  
  3. /**
  4. * 文件名称: com.stu.dao.BankDao.java<br/>
  5. * 初始作者: Administrator<br/>
  6. * 创建日期: 2018-2-5<br/>
  7. * 功能说明:bank的Dao层 <br/>
  8. * =================================================<br/>
  9. * 修改记录:<br/>
  10. * 修改作者 日期 修改内容<br/>
  11. * ================================================<br/>
  12. * Copyright (c) 2010-2011 .All rights reserved.<br/>
  13. */
  14. public interface BankDao {
  15.  
  16. /**
  17. * 方法描述: [修改卡里余额]<br/>
  18. * 初始作者: Administrator<br/>
  19. * 创建日期: 2018-2-5-下午03:08:31<br/>
  20. * 开始版本: 2.0.0<br/>
  21. * =================================================<br/>
  22. * 修改记录:<br/>
  23. * 修改作者 日期 修改内容<br/>
  24. * ================================================<br/>
  25. *
  26. * @param cardId
  27. * 银行卡卡号
  28. * @param money
  29. * 转账金额
  30. * @return
  31. * int 修改条数
  32. */
  33. int editBalance(int cardId, int money);
  34. }

    

    BankDaoImpl.java

  1. package com.stu.dao.impl;
  2.  
  3. import org.springframework.jdbc.core.JdbcTemplate;
  4.  
  5. import com.stu.dao.BankDao;
  6.  
  7. /**
  8. * 文件名称: com.stu.dao.impl.BankDaoImpl.java<br/>
  9. * 初始作者: Administrator<br/>
  10. * 创建日期: 2018-2-5<br/>
  11. * 功能说明: Bank的Dao实现类<br/>
  12. * =================================================<br/>
  13. * 修改记录:<br/>
  14. * 修改作者 日期 修改内容<br/>
  15. * ================================================<br/>
  16. * Copyright (c) 2010-2011 .All rights reserved.<br/>
  17. */
  18. public class BankDaoImpl implements BankDao {
  19.  
  20. private JdbcTemplate jdbcTemplate;
  21.  
  22. @Override
  23. public int editBalance(int cardId, int money) {
  24.  
  25. return jdbcTemplate.update("update bank set balance=balance+? where cardid=?", new Object[] {
  26. money, cardId
  27. });
  28. }
  29.  
  30. public JdbcTemplate getJdbcTemplate() {
  31.  
  32. return jdbcTemplate;
  33. }
  34.  
  35. public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
  36.  
  37. this.jdbcTemplate = jdbcTemplate;
  38. }
  39.  
  40. }

    

    BankService.java

  1. package com.stu.service;
  2.  
  3. /**
  4. * 文件名称: com.stu.service.BankService.java<br/>
  5. * 初始作者: Administrator<br/>
  6. * 创建日期: 2018-2-5<br/>
  7. * 功能说明: Bank的Service层 <br/>
  8. * =================================================<br/>
  9. * 修改记录:<br/>
  10. * 修改作者 日期 修改内容<br/>
  11. * ================================================<br/>
  12. * Copyright (c) 2010-2011 .All rights reserved.<br/>
  13. */
  14. public interface BankService {
  15.  
  16. /**
  17. * 方法描述: [转账的操作]<br/>
  18. * 初始作者: Administrator<br/>
  19. * 创建日期: 2018-2-5-下午03:07:40<br/>
  20. * 开始版本: 2.0.0<br/>
  21. * =================================================<br/>
  22. * 修改记录:<br/>
  23. * 修改作者 日期 修改内容<br/>
  24. * ================================================<br/>
  25. *
  26. * @param form
  27. * @param to
  28. * @param money
  29. * void
  30. */
  31. void tarns(int form, int to, int money);
  32. }

    BankServiceImpl.java

  1. package com.stu.service.impl;
  2.  
  3. import java.io.FileNotFoundException;
  4.  
  5. import org.springframework.transaction.annotation.Isolation;
  6. import org.springframework.transaction.annotation.Propagation;
  7. import org.springframework.transaction.annotation.Transactional;
  8.  
  9. import com.stu.dao.BankDao;
  10. import com.stu.service.BankService;
  11.  
  12. /**
  13. * 文件名称: com.stu.service.impl.BankServiceImpl.java<br/>
  14. * 初始作者: Administrator<br/>
  15. * 创建日期: 2018-2-5<br/>
  16. * 功能说明: BankService层的实现类<br/>
  17. * =================================================<br/>
  18. * 修改记录:<br/>
  19. * 修改作者 日期 修改内容<br/>
  20. * ================================================<br/>
  21. * Copyright (c) 2010-2011 .All rights reserved.<br/>
  22. */
  23. @Transactional
  24. public class BankServiceImpl implements BankService {
  25.  
  26. private BankDao bankDao;
  27.  
  28. /**
  29. * isolation: 隔离级别
  30. * propagation: 传播行为
  31. * rollbackFor: 指定什么类型的异常才回滚,默认为运行时异常
  32. * noRollbackFor: 指定发生什么类型的异常不会滚,默认遇到检查异常不会自动回滚
  33. */
  34. @Override
  35. @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = {
  36. FileNotFoundException.class, NullPointerException.class, NumberFormatException.class })
  37. public void tarns(int form, int to, int money) {
  38.  
  39. try {
  40. bankDao.editBalance(form, -money);
  41. bankDao.editBalance(to, money);
  42. } catch (Exception e) {
  43. e.printStackTrace();
  44. // Service中的异常一定要向上抛出,否则@Transactional对应的注解解析器,无法捕获到 对应的切入点(被@Transactional注解标记的方法)抛出的异常,无法进行事务的回滚操作
  45. throw new RuntimeException(e);
  46. }
  47. }
  48.  
  49. public BankDao getBankDao() {
  50.  
  51. return bankDao;
  52. }
  53.  
  54. public void setBankDao(BankDao bankDao) {
  55.  
  56. this.bankDao = bankDao;
  57. }
  58.  
  59. }

  因为切面的切入点是该类中的方法上,所以使用Transaction注解

  Demo02.java

  1. package com.stu.demo;
  2.  
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;
  5.  
  6. import com.stu.service.BankService;
  7.  
  8. /**
  9. * 文件名称: com.stu.demo.Demo02.java<br/>
  10. * 初始作者: Administrator<br/>
  11. * 创建日期: 2018-2-5<br/>
  12. * 功能说明: AspectJ事务操作 <br/>
  13. * =================================================<br/>
  14. * 修改记录:<br/>
  15. * 修改作者 日期 修改内容<br/>
  16. * ================================================<br/>
  17. * Copyright (c) 2010-2011 .All rights reserved.<br/>
  18. */
  19. public class Demo02 {
  20.  
  21. public static void main(String[] args) {
  22.  
  23. ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContextForAspectJ.xml");
  24. BankService bankService = ac.getBean("bankService", BankService.class);
  25. //从 卡号1 向 卡号2 中转账100块
  26. bankService.tarns(1, 2, 100);
  27. }
  28. }

    applicationContextForAspectJ.xml

  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" xmlns:context="http://www.springframework.org/schema/context"
  4. xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"
  5. xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
  6. xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util"
  7. xmlns:jpa="http://www.springframework.org/schema/data/jpa"
  8. xsi:schemaLocation="
  9. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
  10. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
  11. http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
  12. http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
  13. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
  14. http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
  15. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
  16. http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
  17. http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
  18.  
  19. <!-- 通过 XML配置文件读取jdbc.properties中的数据库配置信息 -->
  20. <util:properties id="dbConfig" location="classpath:jdbc.properties"></util:properties>
  21.  
  22. <!-- 定义jdbc的数据源 -->
  23. <bean id="ds" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource">
  24. <property name="driverClassName" value="#{dbConfig.driver}"></property>
  25. <property name="url" value="#{dbConfig.url}"></property>
  26. <property name="username" value="#{dbConfig.username}"></property>
  27. <property name="password" value="#{dbConfig.userpwd}"></property>
  28. </bean>
  29.  
  30. <!-- 配置Spring中的JDBC对象 -->
  31. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  32. <property name="dataSource" ref="ds"></property>
  33. </bean>
  34.  
  35. <bean id="namedJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
  36. <constructor-arg index="0" ref="ds"></constructor-arg>
  37. </bean>
  38.  
  39. <!-- 使用AspectJ事务管理 -->
  40. <!--
  41. 开启AspectJ的自动代理
  42. 当Spring容器在初始化时,通过@Aspect注解找到切面类
  43. 根据<aop:aspectj-autoproxy />配置,将切面自动作用到目标方法上
  44. -->
  45. <aop:aspectj-autoproxy />
  46.  
  47. <!-- 使用AspecJ事务管理切面 -->
  48. <bean id="txAspect" class="com.stu.aspect.TransactionAspect">
  49. <property name="ds" ref="ds"></property>
  50. </bean>
  51.  
  52. <bean id="bankDao" class="com.stu.dao.impl.BankDaoImpl">
  53. <property name="jdbcTemplate" ref="jdbcTemplate"></property>
  54. </bean>
  55. <bean id="bankService" class="jdbcTemplate"></bean> </beans>

C.编程式事务,

  不推荐使用,事务管理和业务耦合度高,侵入性高

  使用编程式事务时,Spring提供以下两种事务管理的API(推荐使用前者)

  1,使用TransactionTemplate

  2,直接使用一个PlatformTransactionManager实现,(但是一般使用DataSourceTransactionManager)

  TransactionTemplate与JdbcTemplate等模板类的使用风格相似,它也使用回调机制,将事务代码和业务代码分离,这样便于开发者把精力集中在具体的业务编程上。

  

  applicationContext.xml配置文件

  1. <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  2. <property name="dataSource" ref="ds"/>
  3. </bean>
  4. <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
  5. <property name="transactionManager" ref="txManager"/>
  6. <property name="propagationBehavior" value="0"></property>
  7. <property name="isolationLevel" value="2"></property>
  8. <property name="readOnly" value="true"></property>
  9. </bean>

(1)如果需要返回值,则传递TransactionCallback匿名内部类

  1. public boolean trans1(final int money, int from, int to) {
  2.  
  3. Boolean result = null;
  4. try {
  5. result = transactionTemplate.execute(new TransactionCallback<Boolean>() {
  6.  
  7. @Override
  8. public Boolean doInTransaction(TransactionStatus status) {
  9.  
  10. try {
  11. bankDao.updateBalance(-money, 1);
  12. if (1 == 1) {
  13. throw new RuntimeException("转账过程中出错了!");
  14. }
  15. bankDao.updateBalance(money, 2);
  16. return true;
  17. } catch (RuntimeException e) {
  18. e.printStackTrace();
  19. status.setRollbackOnly();
  20. return false;
  21. }
  22. }
  23. });
  24. } catch (Exception e) {
  25. e.printStackTrace();
  26. }
  27. return result;
  28. }

测试:

  1. public static void main(String[] args) {
  2.  
  3. ApplicationContext ac =
  4. new ClassPathXmlApplicationContext("applicationContext.xml");
  5. BankService bankService = ac.getBean("bankService", BankService.class);
  6. boolean result = bankService.trans4(50, 1, 2);
  7. System.out.println(result);
  8. ((AbstractApplicationContext) ac).close();
  9. }

(2)如果不需要返回值,可以创建一个TransactionCallbackWithoutResult匿名类

  1. @Override
  2. public boolean trans2(final int money, int from, int to) {
  3. try {
  4. transactionTemplate.execute(new TransactionCallbackWithoutResult() {
  5. @Override
  6. protected void doInTransactionWithoutResult(TransactionStatus status) {
  7. try {
  8. bankDao.updateBalance(-money, 1);
  9. if (1 == 1) {
  10. throw new RuntimeException("转账过程中出错了!");
  11. }
  12. bankDao.updateBalance(money, 2);
  13. } catch (RuntimeException e) {
  14. e.printStackTrace();
  15. status.setRollbackOnly();
  16. }
  17. }
  18. });
  19. return true;
  20. } catch (Exception e) {
  21. e.printStackTrace();
  22. return false;
  23. }
  24. }

使用XML配置事务

在上面的基础上进行修改

applicationContextForXML.xml

  1. <!-- 通过 XML配置文件读取jdbc.properties中的数据库配置信息 -->
  2. <util:properties id="dbConfig" location="classpath:jdbc.properties"></util:properties>
  3.  
  4. <!-- 定义jdbc的数据源 -->
  5. <bean id="ds" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource">
  6. <property name="driverClassName" value="#{dbConfig.driver}"></property>
  7. <property name="url" value="#{dbConfig.url}"></property>
  8. <property name="username" value="#{dbConfig.username}"></property>
  9. <property name="password" value="#{dbConfig.userpwd}"></property>
  10. </bean>
  11.  
  12. <!-- 配置Spring中的JDBC对象 -->
  13. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  14. <property name="dataSource" ref="ds"></property>
  15. </bean>
  16.  
  17. <bean id="namedJdbcTemplate"
  18. class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
  19. <constructor-arg index="0" ref="ds"></constructor-arg>
  20. </bean>
  21.  
  22. <!-- 使用XML配置文件进行事务管理 -->
  23. <!-- 配置事务相关的属性 -->
  24. <tx:advice id="txAdvice" transaction-manager="transactionManager">
  25. <tx:attributes>
  26. <!-- 配置事务相关的属性 -->
  27. <!--
  28. name:方法名 propagation:隔离级别 isolation:传播方法 rollback-for:遇到什么异常回滚
  29. no-rollback-for:遇到什么异常不回滚
  30. -->
  31. <tx:method name="trans*" propagation="REQUIRED" isolation="READ_COMMITTED"
  32. rollback-for="java.lang.RuntimeException" />
  33.  
  34. <!--
  35. <tx:method name="trans*" propagation="REQUIRED" isolation="READ_COMMITTED" rollback-for="java.lang.RuntimeException"/>
  36. <tx:method name="trans*" propagation="REQUIRED" isolation="READ_COMMITTED" rollback-for="java.lang.RuntimeException"/>
  37. -->
  38. </tx:attributes>
  39. </tx:advice>

[Spring-AOP-XML] 利用Spirng中的AOP和XML进行事务管理的更多相关文章

  1. [Spring] Spirng中的AOP进行事务的传播属性和事务隔离级别

    通知注解 前置通知(@Before):在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常) 返回后通知(@AfterReturning):在某连接点 ...

  2. Mybatis 的 Xml 映射文件中,不同的 Xml 映射文件,id 是否可以重复?

    不同的 Xml 映射文件,如果配置了 namespace,那么 id 可以重复:如果没有配 置 namespace,那么 id 不能重复: 原因就是 namespace+id 是作为 Map<S ...

  3. 二十 Spring的事务管理及其API&事务的传播行为,编程式&声明式(xml式&注解式,底层AOP),转账案例

    Spring提供两种事务方式:编程式和声明式(重点) 前者需要手写代码,后者通过配置实现. 事务的回顾: 事务:逻辑上的一组操作,组成这组事务的各个单元,要么全部成功,要么全部失败 事务的特性:ACI ...

  4. Spring 事务管理tx,aop

    spring tx:advice事务配置 2016年12月21日 17:27:22 阅读数:7629 http://www.cnblogs.com/rushoooooo/archive/2011/08 ...

  5. Spring事务管理—aop:pointcut expression 常见切入点表达式及事物说明

    例: <aop:config>  <aop:pointcut expression="execution(* com.xy.service.*.*(..))"   ...

  6. Spring事务管理—aop:pointcut expression 常见切入点表达式及事务说明

    Spring事务管理—aop:pointcut expression 常见切入点表达式及事物说明 例: <aop:config>  <aop:pointcut expression= ...

  7. Spring -- spring结合aop 进行 tx&aspectj事务管理配置方法

    1. tx 配置方法, 代码示例 javabean及其映射文件省略,和上篇的一样 CustomerDao.java, dao层接口 public interface CustomerDao { pub ...

  8. Spring Boot 中使用 @Transactional 注解配置事务管理

    事务管理是应用系统开发中必不可少的一部分.Spring 为事务管理提供了丰富的功能支持.Spring 事务管理分为编程式和声明式的两种方式.编程式事务指的是通过编码方式实现事务:声明式事务基于 AOP ...

  9. Spring Boot中使用@Transactional注解配置事务管理

    事务管理是应用系统开发中必不可少的一部分.Spring 为事务管理提供了丰富的功能支持.Spring 事务管理分为编程式和声明式的两种方式.编程式事务指的是通过编码方式实现事务:声明式事务基于 AOP ...

随机推荐

  1. Ubuntu下忘记MySQL root密码解决方法

    1.忘了mysql密码,从网上找到的解决方案记录在这里. 编辑mysql的配置文件/etc/mysql/my.cnf,在[mysqld]段下加入一行“skip-grant-tables”. 2.重启服 ...

  2. ATOM常用插件推荐

    转载:http://blog.csdn.net/qq_30100043/article/details/53558381 ATOM常用插件推荐 simplified-chinese-menu ATOM ...

  3. png文件格式详解,获取文件的修改时间,创作时间

    http://dev.gameres.com/Program/Visual/Other/PNGFormat.htmhttp://www.360doc.com/content/11/0428/12/10 ...

  4. RESTful API单元测试(十九)

    下面针对该Controller编写测试用例验证正确性,具体如下.当然也可以通过浏览器插件等进行请求提交验证. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ...

  5. 模块之 logging, shelve, sys 模块

    一. logging模块 用来记录日志,日志:记录某个时间点发生了什么事 日志作用:程序调试 了解软件程序的运行情况,是否正常 软件程序运行故障分析与问题定位 还可用来做用户行为分析 日志等级:在不改 ...

  6. axios ajax fetch 区别

    请求方式千千万,axios是一种对ajax的封装,fetch是一种浏览器原生实现的请求方式,跟ajax对等

  7. 强制ubuntu登陆用户退出

    #skill -KILL -u user1 杀死并注销user1. #skill -CONT -u user1 恢复user1. 在Windows 2003默认情况下,三个以上就远程不了,必须强制登录 ...

  8. react router @4 和 vue路由 详解(七)react路由守卫

    完整版:https://www.cnblogs.com/yangyangxxb/p/10066650.html 12.react路由守卫? a.在之前的版本中,React Router 也提供了类似的 ...

  9. 用socket.io将Node后台与M站相联系

      目的:用socket.io将Node后台与M站相联系,实现当Node后台添加一条数据时,调用该接口的M站不用手动刷新自动出现新增的数据     具体实现:当在后台系统position列表中添加/修 ...

  10. 003-RHEL7-Linux系统维护管理命令使用

    系统维护管理命令: date  查看日期,设置日期 只有超级用户才能用date命令设置时间 date  --help  显示时间的帮助命令 date{选项} 显示时间格式(以+开头,后面接时间格式) ...