在Spring AOP切面中启用新事务

Posted swnchx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Spring AOP切面中启用新事务相关的知识,希望对你有一定的参考价值。

在工作中有一个在切面中需要记录一下操作日志的需求,而且要求这些操作日志要存入数据库,并且无论业务层有什么异常,日志照常记录,那就不能沿用业务层的事务,而是需要新启一个事务了。
sping的声明式事务就是靠AOP来实现的,一般事务都在业务层中启用,那如果要在AOP的逻辑中启用一个新的事务要怎么做呢?比如下面的例子:

//定义一个切点,这里指com.lidehang.remote包下所有的类的方法
@Pointcut("execution(public * com.lidehang.remote..*.*(..))")
 public void remote(){}

//切点指定的方法执行完返回后调用
@AfterReturning(returning = "ret", pointcut = "remote()")
 public void doAfterReturning(JoinPoint joinPoint,Object ret) throws Throwable {
    //一些切面逻辑,包含了数据库操作,为了即便业务层的原事务回滚也不会影响切面中的数据库操作,需要启用新的事务
...
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

经过我的测试,通过在doAfterReturning方法上加上注解@Transactional,并指定传播行为是REQUIRES_NEW依然不行。因为@Transactional也是声明式事务,本身就是AOP实现的,在AOP的代码中使用不起作用。所以就只能使用spring的编程式事务了,需要引入TransactionTemplate。如下:

@Autowired
private TransactionTemplate transactionTemplate;

@AfterReturning(returning = "ret", pointcut = "remote()")
 public void doAfterReturning(JoinPoint joinPoint,Object ret) throws Throwable {
//声明式事务在切面中不起作用,需使用编程式事务
//设置传播行为:总是新启一个事务,如果存在原事务,就挂起原事务
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
transactionTemplate.execute(new TransactionCallback<T>() {
@Override
        public T doInTransaction(TransactionStatus arg0) {
            //一些切面逻辑,包含了数据库操作
...
}
});
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

通过以上的步骤,切面里的逻辑会在新事务中执行,执行完就会提交,和业务层中的原事务无关,即便执行完切面逻辑后继续执行业务代码的过程中出现异常,业务层中的数据库操作因为有原事务而回滚,但切面中的数据库操作不会回滚,因为这是个新的事务!

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net


以上是关于在Spring AOP切面中启用新事务的主要内容,如果未能解决你的问题,请参考以下文章

三面向切面编程

AOP

spring学习笔记(23)基于tx/aop配置切面增强事务

Spring——面向切面编程(AOP模块)

Spring AOP面向切面编程详解

Spring AOP 切面增强