‘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