aop切面编程的时候,类内部调用出现注解失效的情况

aop切面编程的时候,类内部调用出现注解失效的情况

问题描述: 我们在使用AOP的时候,有时候会出现注解失效的情况,而常见的原因就是类内部的方法调用,这里结合具体的示例代码来讨论这个问题。(刚开始写博客,有错误和不足之处,欢迎大家的批评和指正

下面是示例代码:

自定义注解:

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AopTest {
    String name() default "";
}

切面处理:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
public class AopAspect {

    @Pointcut("@annotation(com.myaop.AopTest)")
    public void aopTestPointCut(){

    }

    @Around("aopTestPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable{
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        AopTest annotation = method.getAnnotation(AopTest.class);
        System.out.println("进入切面,开始执行 : " + annotation.name());
        return point.proceed();
    }
}

从上面代码可以看出,方法添加注解后,在调用时会先执行around()方法中的内容,也就是先输出 : “进入切面,开始执行 : ” 。
下面测试一下:

import org.springframework.stereotype.Service;

@Service
public class TestService {

    @AopTest(name="A事件")
    public void methodA(){
        System.out.println("正在执行A事件。。。。。。。。");
    }

    @AopTest(name="B事件")
    public void methodB(){
        System.out.println("正在执行B事件。。。。。。。。");
    }

    public void methodC(){
        System.out.println("正在执行C事件。。。。。。。。");
        methodA();
    }

    @AopTest(name="B事件")
    public void methodD(){
        System.out.println("正在执行D事件。。。。。。。。");
        methodF();
    }

    public void methodF(){
        System.out.println("正在执行F事件。。。。。。。。");
    }


    public void methodG(){
        System.out.println("正在执行G事件。。。。。。。。");
        methodA();
    }


}

新建一个Controller来测试一下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MainTestController {
    @Autowired
    private TestService testService;

    @RequestMapping("/test")
    @ResponseBody
    public void test1(){
        testService.methodA();
    }

}

当调用 testService.methodA()时,会先进入切面,结果如下:
在这从里插入图片描述
这是我们最常用的使用场景。接下来讨论有可能出现注解失效的场景,分三种情况来讨论:
A(有注解) ------调用----- B(无注解)
A(无注解) ------ 调用 ---- B(有注解)
A(有注解) ------ 调用------ B(有注解)
A和B都是类里面的方法,我们这里讨论的是内部方法调用的情况。

先看第一种 A(有注解) ------调用----- B(无注解):
controller 中调用 testService.methodD(); 结果如下:
在这里插入图片描述从结果可以看出,只有加了注解的方法才会进入切面。因为spring生成bean的时候扫描了有注解的方法,如果扫描到注解会生成代理类,通过代理类加入了对切面的处理。

class proxy$TestService{

    TestService testService = new TestService();

    void methodD(){
        startTransaction();
        testService.methodD();
    }

    void methodF(){
        //由于methodF()没有注解,所以不会启动transaction,而是直接调用TestService的实例的methodF()方法
        testService.methodF(); 
    }
}

第二种执行testService.methodC();A(无注解) ------ 调用 ---- B(有注解)
在这里插入图片描述这里可以看到,当我们controller在进行调用A时,如果A无注解,B有注解,这时B上面的注解会失效。因为在方法内部调用时,会使用原生的bean去调用,而不会生成的代理类去调用,所以B的注解会失效。

第三种:A(有注解) ------ 调用------ B(有注解)
在这里插入图片描述如果A有注解,B有注解,这时B上面的注解也会失效。因为在方法内部调用时,会使用原生的bean去调用,而不会生成的代理类去调用,所以B的注解也会失效。

解决这种原因导致注解失效的最好的方法就是将方法拆分为不同的类,避免内部调用。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值