AOP注解式事务失效问题

最近在工作中遇到使用事务。一直使用的都是注解式的事务@Transactional。完成开发自测时发现事务失效了。不科学啊,我写的代码怎么可能有bug!!项目我都搭建过好几个了,一直都是同一个套路,不可能有事务配置错误。于是乎分析了一下,把原因贴出来给大家共享一下。工作中肯定有踩到坑的同学。
首先说一下我的代码结构

// 父类
public abstract class AbstractParentClass {

	public void doSomething(){
		// 1.一些通用逻辑1xxxxx
		// 2.调用抽象方法
		abstractMethod();
		// 3.一些通用逻辑2xxxxx
	}
	
	// 子类实现的抽象方法
	abstract void abstractMethod();

}
// 子类
public class Testclass extends AbstractParentClass {

	// 子类实现方法
	public void abstractMethod(){
		// 1.业务逻辑1
		// 2.调用内部方法
		methodA();
		// 3.业务逻辑2
	}

	private void methodA(){
	}

}

类的关系式是存在两个类,父类封装了一些通用逻辑,暴露了一个抽象方法给子类去实现。
子类对抽象方法进行了实现,方法内部又调用了自己的若干方法。

以上是代码结构关系的介绍。相信这种设计在工作中很常见。我的情景是在子类的methodA方法中有需要加事务的操作。我就很果断的在方法methodA上加了事务注解@Transactional

有经验的小伙伴可能立马就能发现一个问题,方法methodAprivate的,事务不会生效。这是一个错误。我开始也是把private修改成了public,但是仍然不行。
问题在哪里呢?想一下,我们的事务是如何实现的?AOP。
比喻一下,既然是AOP的话,那得有一个触发机制,当切面外部调用到实现类具体的方法时,穿过了切面,出发了事务。而我上面的代码是Testclass方法abstractMethod调用了自己的方法methodA,没有经过切面,所以没有触发事务。这个比喻我觉得应该有助于理解。
专业一点解释的话呢,大家都叫这是一个AOP的缺陷。当类内部方法相互调用的时候,是不会触发AOP的。那应该怎么做呢,子类做如下修改:

// 子类
public class Testclass extends AbstractParentClass {

	// 子类实现方法
	public void abstractMethod(){
		// 1.业务逻辑1
		// 2.调用内部方法
		// methodA();
		// 调用方式修改为这样
		// 这个方法能获取到aop对象还有一个前提,就是使用了aop。例如@Transactional加到了一个private方法上,那么是会报错的.而且其他配置也要配对
		 ((Testclass)AopContext.currentProxy()).methodA();
		// 3.业务逻辑2
	}
	
	@Transactional
	public void methodA(){
	}

}

记得要在xml配置中配置

<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>

问题根源是类内部不加事务的方法调用加了事务的方法导致的。其他类似的方法调用关系导致的AOP不生效问题可以以此类推。
关于AopContext.currentProxy()的详细使用和配置可以单独去查找,资料很多。

你可能感兴趣的:(Java)