常见的基本注解 :
元注解 : 元注解修饰注解 , 而元注解也是一种注解 (套娃警告) , 它们是一种专门用于修饰非元注解的注解
上图可以看到有两个注解修饰了 @Override , 它们就是其中的两个元注解
JDK 5.0 提供了 4 个元注解 :
@Retension
@Retension 限定注解的生命周期
其中取值有 :
示例 :
/**
* 自定义用户登录注解 , 运行时被该注解标识的方法会判断用户是否登录
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface UserLoginToken {
boolean required() default true;
}
由于 @UserLoginToken 被 RUNTIME
修饰 , 所以在运行时可以通过反射获取到该注解的属性值 , 作额外的逻辑处理
@Target
@Target 指定被修饰的注解能用于修饰哪些作用域
其中取值有 :
@Target 可以同时指定多个作用域 , @UserLoginToken 被标注只能作用再方法和类上 , 示例 :
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserLoginToken {
boolean required() default true;
}
@UserLoginToken 由于被 METHOD
和 TYPE
修饰 , 所以该注解可以修饰 方法 , 类 , 接口 等作用域
@Documented
@Documented 用于指定被该元注解修饰的注解将被 javadoc 工具提取成文档
示例 :
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface UserLoginToken {
boolean required() default true;
}
添加了 @Documented , 就会被 javadoc 工具抓取到文档中
@Inherited
被 @Inherited 注解修饰的注解将具备 继承性 , 即如果某个类使用了被 @Inherited 修饰的注解A , 那么子类也会具备该注解A
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface UserLoginToken {
boolean required() default true;
}
UML 类图结构 :
下面这段代码将会输出 true , 代表子类 Sub 上存在 @UserLoginToken注解
@UserLoginToken
public class Base {
}
public class Sub extends Base {
public static void main(String[] args) {
// true
System.out.println(Sub.class.isAnnotationPresent(UserLoginToken.class));
}
}
如果 @UserLoginToken 去掉 @Inherited 注解 , 程序会输出 false
AnnotatedElement 接口是所有程序元素的父接口 (类 , 接口 , 方法 , 成员等) , 通过反射获取到该对象后 , 可以利用如下方法访问注解信息 :
通过自定义注解 @UserLoginToken 判断用户是否已登录
// 用户登录验证注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserLoginToken {
boolean required() default true;
}
// 允许匿名访问注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PassToken {
boolean required() default true;
}
拦截器拦截请求 :
public class MemberAuthenticationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
// 如果不是映射到方法直接通过
if(!(object instanceof HandlerMethod)){
return true;
}
// 强转成对应方法
HandlerMethod handlerMethod=(HandlerMethod)object;
Method method=handlerMethod.getMethod();
//检查是否有@Passtoken注释,有则跳过认证
if (method.isAnnotationPresent(PassToken.class)) {
PassToken passToken = method.getAnnotation(PassToken.class);
if (passToken.required()) {
return true;
}
}
//检查有没有需要用户权限的注解
if (method.isAnnotationPresent(UserLoginToken.class)) {
// 获取该方法上的注解 , 并获取它的属性值
UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
if (userLoginToken.required()) {
// 执行认证
}
}
return true;
}
}
如果觉得不错 , 欢迎点赞收藏 ! 随时欢迎各位与我交流学习 !