如何在AOP代理的情况下获取注解所在的全限定类名

如何在AOP代理的情况下获取注解所在的全限定类名
在通过AOP切片来使用Redis缓存加速的时候,势必会涉及key的取值,一个比较好的方法是自定义注解+方法名称+参数+全限定类名。但是在获取全限定类名的时候遇到了一些问题,现记录下来。

直接上最终的解决方案

@Around("@annotation(com.ava.ww.common.cache.RedisCache)")
public Object redisAspectMethod(ProceedingJoinPoint point) {

  // 获取缓存key
  MethodSignature signature = (MethodSignature) point.getSignature();
  
  // 获取Method对象
  Method method = signature.getMethod();
  
  RedisCache annotation = method.getAnnotation(RedisCache.class);

  // 拼接缓存key,注解+方法名+参数+全限定类名
  String redisKey = annotation.prefix() + method.getName() + "_" + Arrays.toString(point.getArgs()) + "_" + point.getTarget().getClass().getName();

  // 此处省略分布式锁访问过程
  ...
  
  return dataFromDatabase;

}

正确获取被代理对象全限定类名的方法

point.getTarget().getClass().getName()

为什么不能通过以下方式获取全限定类名?

MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
Class declaringClass = method.getDeclaringClass();
String fqcn = declaringClass.getName();

这是因为在Spring AOP代理的情况下,JoinPoint获取到的签名对象是JDK动态代理生成的一个内部类,并不是原始类的方法签名。

Spring AOP是基于动态代理实现的,当目标对象被代理时,实际调用的是动态生成的代理类的方法,所以该方法的签名是代理类的内部方法签名,而不是原始类的方法签名。

具体来看,在Spring AOP中,ProceedingJoinPointgetSignature()获取的是MethodSignature,而这个MethodSignature的实际类型是org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$MethodSignatureImpl

这是一个JDK动态代理内部生成的类,用于描述当前被调用方法的信息,但不代表原始类本身。

所以通过getSignature()获得的签名表示的是代理类的内部方法调用,而不是原始类的方法调用,自然无法获取到原始类的全限定类名。

总结

要获取原始类的全限定类名,可以通过ProceedingJoinPointgetTarget()获取被代理的原始对象,然后通过originalObject.getClass().getName()获取原始类全限定类名。

这种方式可以跳过代理,直接获取到目标对象的实际类型,从而获得原始类的全限定类名。

Spring AOP代理会影响JoinPoint获取到的方法签名,需要特殊处理才能获取到原始类信息,这与其动态代理机制有关。

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值