Spring AOP当方法被内部调用时,增强逻辑失效问题原因及解决方案

首先,这个问题本质原因和我之前写的这篇文章《Spring事务调用类自己方法失效解决办法和原因》是一样的,都是动态代理失效导致的。

最近在开发中遇到了一个关于Spring AOP的问题。需求是统计某个方法的调用次数,我尝试使用Spring AOP来实现,但发现当方法被内部调用时,增强逻辑不生效。以下是详细描述和解决方案。

问题描述

我定义了一个接口ISon,包含方法A和方法B。在接口实现类Son中,方法B调用了方法A。同时,我通过AOP切面对方法A进行了增强。测试发现,当直接调用A时,增强逻辑正常工作;但当通过方法B调用A时,增强逻辑失效。

public interface ISon {
    void A();
    void B();
}
@Service
public class Son implements ISon {
    @Override
    public void A() {
        System.out.println("method A");
    }
    @Override
    public void B() {
        System.out.println("method B");
        A();
    }
}
@Aspect
@Component
public class AspectDemo {

    @Pointcut(value = "execution(* com.example.transactiondemo.aop.ISon.A(..))")
    public void pointCut(){
    }

    @Before("pointCut()")
    public void before(JoinPoint joinPoint){
        System.out.println("before ");
    }

    @After("pointCut()")
    public void after(){
        System.out.println("after ");
    }

}
@Autowired
private ISon iSon;

@Test
public void test11(){
    iSon.A();
    System.out.println("-----------");
    iSon.B();
}
before 
method A
after 
-----------
method B
method A

失效原因

原因在于,方法A被调用是基于AOP生成的代理对象进行的调用;而方法B调用方法A时,是直接通过this目标对象调用,并不是通过代理对象。

解决方案

为了解决这个问题,我需要确保即使是内部调用也能触发增强逻辑。一种方法是使用AopContext.currentProxy()来获取代理对象,并调用其方法。同时,需要在应用配置中开启AOP支持,并暴露代理对象。

  1. 开启AOP支持:在应用配置中添加以下注解:

    @EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)
    
  2. 修改方法调用:在方法B中,不直接调用A,而是通过代理对象调用:

    @Override
    public void B() {
        System.out.println("method B");
        ((Son) AopContext.currentProxy()).A();
    }
    
  3. 获取上下文的Bean再调用:另一种方法是通过应用上下文获取Bean,然后调用其方法:

    @Autowired
    private ApplicationContext applicationContext;
    
    ((Son) applicationContext.getBean(Son.class)).A();
    

通过这些修改,无论是直接调用还是内部调用,方法A的增强逻辑都能正常工作。这样,我就可以准确统计方法的调用次数了。

posted @ 2024-07-17 18:53  夏威夷8080  阅读(8)  评论(0编辑  收藏  举报