用反射获取方法上的自定义注解,关于元注解@Retention
自己做的一个用JWT对接口安全验证的demo。自定义了一个@PassToken注解,用拦截器拦截通过的所有接口地址,给登录接口加@PassToken表示不需要验证token,其他接口无此注解则需要验证token。
public class AuthenticationInterceptor implements HandlerInterceptor {
@Autowired
private RedisUtil redisUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if(!(handler instanceof HandlerMethod)){
return true;
}
HandlerMethod handlerMethod= (HandlerMethod) handler;
Method method=handlerMethod.getMethod();
PassToken passToken=method.getDeclaredAnnotation(PassToken.class);
if(passToken!=null){
return true;
}
String token=request.getHeader("token");
if(StringUtils.isNotBlank(token)){
if(redisUtil.hasKey(token)){
return true;
}
}else{
throw new TokenNotFoundException("缺失token");
}
return false;
}
}
之前这样获取的passToken对象一直都是null,于是看了一下我定义的注解:
@Inherited
@Documented
public @interface PassToken {
boolean value() default true;
},
当时我为了图简单就加了两个不需要属性的元注解 @Inherited和@Documented。但是这样通过反射获取不到接口方法上的注解@PassToken,于是把四个元注解都加上了:
@Inherited
@Documented
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PassToken {
boolean value() default true;
}。
当时只知道@Retention这个注解的属性是一个枚举类型,有三个值,source,class,runtime,分别对应着注解存在于java文件,class文件和运行时,
但是对具体的作用不是很清楚。后面查了下。
RetentionPolicy.SOURCE注解相当于帮我们对语法做检查或提示作用,例如@Override注解,告诉我们这个方法是重写的,当java文件被编译成class文件之后它就不存在了,
RetentionPolicy.CLASS帮我们做一些预处理的比如lombok的@Data注解,它可以让我们在编写java类时省去setter,getter和构造方法等,
等java文件被编译成class文件时会自动帮我们生成setter,getter和构造器等方法。
只有RetentionPolicy.RUNTIME会在运行时起作用,可以通过反射被获取到,如@Autowired注解,可以将在运行时将bean注入到另一个bean的属性当中。

浙公网安备 33010602011771号