Spring AOP 对象内部方法间的嵌套调用

前两天面试的时候,面试官问了一个问题,大概意思就是一个类有两个成员方法 A 和 B,两者都加了事务处理注解,定义了事务传播级别为 REQUIRE_NEW,问 A 方法内部直接调用 B 方法时能否触发事务处理机制。

答案有点复杂,Spring 的事务处理其实是通过AOP实现的,而实现AOP的方法有好几种,对于通过 Jdk 和 cglib 实现的 aop 处理,上述问题的答案为否,对于通过AspectJ实现的,上述问题答案为是。

本文就结合具体例子来看一下,我们先定义一个接口

public interface AopActionInf {
    void doSomething_01();

    void doSomething_02();
}

以及此接口的一个实现类,

public class AopActionImpl implements AopActionInf{
    public void doSomething_01() {
        System.out.println("AopActionImpl.doSomething_01()");

        //内部调用方法 doSomething_02
        this.doSomething_02();
    }

    public void doSomething_02() {
        System.out.println("AopActionImpl.doSomething_02()");
    }
}

增加AOP处理

public class ActionAspectXML {

    public Object aroundMethod(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("进入环绕通知");
        Object object = pjp.proceed();//执行该方法
        System.out.println("退出方法");
        return object;
    }

}


"actionImpl" class="com.maowei.learning.aop.AopActionImpl"/>
"actionAspectXML" class="com.maowei.learning.aop.ActionAspectXML"/>


    "aspectXML" ref="actionAspectXML">
        "anyMethod" expression="execution(* com.maowei.learning.aop.AopActionImpl.*(..))"/>
        "aroundMethod" pointcut-ref="anyMethod"/>
    

运行结果如下:
Spring AOP 对象内部方法间的嵌套调用_第1张图片

下图是断点分析在调用方法doSomething_02时的线程栈,很明显在调用doSomething_02时并没有对其进行AOP处理。
Spring AOP 对象内部方法间的嵌套调用_第2张图片

默认情况下,Spring AOP使用Jdk的动态代理机制实现,当然也可以通过如下配置更改为cglib实现,但是运行结果相同,此处不再赘述。

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

那有没有办法能够触发AOP处理呢?答案是有的,考虑到AOP是通过动态生成目标对象的代理对象而实现的,那么只要在调用方法时改为调用代理对象的目标方法即可。

我们将调用 doSomething_02 的那行代码改成如下,并修改相应配置信息:

public void doSomething_01() {
    System.out.println("AopActionImpl.doSomething_01()");
    ((AopActionInf) AopContext.currentProxy()).doSomething_02();
}

"true"/>

先来看一下运行结果,
Spring AOP 对象内部方法间的嵌套调用_第3张图片

从运行结果可以看出,嵌套调用方法已经能够实现AOP处理了,同样我们看一下线程调用栈信息,显然 doSomething_02 方法被增强处理了(红框中内容)。
Spring AOP 对象内部方法间的嵌套调用_第4张图片

你可能感兴趣的:(重学Spring)