(排坑)自定义注解通过Method类‘getAnnotation()’取值为‘NULL’

本文探讨了在使用AspectJ 1.8.9版本时,注解类的`@Test`在`@Around`切面中无法正确获取的问题,通过检查注解应用、目标对象与代理对象的关系,以及如何确保方法级注解被正确继承。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

‘aspectj’版本:1.8.9 (绝大部分版本针对此问题不会有影响)

依赖如下:

<dependency>
  	<groupId>org.aspectj</groupId>
   	<artifactId>aspectjweaver</artifactId>
   	<version>1.8.9</version>
</dependency>

先从注解类开始检查

注解类

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
@Order(Ordered.HIGHEST_PRECEDENCE)
public @interface Test {

    int value() default 9;
    
}
  • @Retention: 定义被它所注解的注解保留多久

source注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;被编译器忽略
class注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期
runtime注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在

  • @Target: 注解的作用目标
  • @Documented: 标记注解,表明这个注解应该被 javadoc工具记录
  • @Order: 定义Spring IOC容器中Bean的执行顺序的优先级

Aspect类

import cn.annotation.APILimit;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;


@Aspect
@Component
public class TestAspect {

    private Logger logger = LoggerFactory.getLogger(TestAspect.class);


    @Pointcut("execution(* cn.controller..*.*(..))")
    public void before(){
    }

    @Before("before()")
    public Void handle(ProceedingJoinPoint joinPoint) throws Exception {

        // 获取HttpRequest
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        // 判断request不能为空
        if (request == null) {
            throw new Exception("HttpServletRequest获取有误...");
        }

        Test test = this.getAnnotation(joinPoint);
        logger.info(test.toString());
        
    }

    // 获取注解
    private Test getAnnotation(JoinPoint joinPoint) throws Exception {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null) {
            return method.getAnnotation(Test.class);
        }
        return null;
    }


}

  • 入参类: ‘ProceedingJoinPoint ’与‘JoinPoint’都能获取到接口信息,对于获取注解类无影响

重点是‘getAnnotation()’函数获取值为NULL

网上大部分博客说明此处是‘目标对象’和‘代理对象’的问题
比起这个,先检查拦截的方法是否有声明指定类型的注解(绝大部分都是因为这个原因导致)

Method.getAnnotation(Class< T > annotationClass)

  • 如果该方法对象存在指定类型的注解,则返回该注解,否则返回 null
  • 只有类级别的注解会被继承得到,对于其他对象而言,getAnnotation() 方法与 getDeclaredAnnotation() 方法作用相同
	例如一个方法:
	    @Override
	    @SneakyThrows
	    public void method1(){}

	method.getAnnotation(Test.class) == NULL
	method.getAnnotation(Override.class) != NULL 
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值