唐僧喜欢小龙女

导航

自定义注解的理解和使用

1、自定义注解的理解

/**
 *
 *  一、自定义注解
 *  1、使用@interface 来标识
 *  2、内部成员变量通常使用value来表示
 *  3、可以指定成员变量的默认值 使用 default 来定义
 *  4、如果自定义的注解没有 成员变量 表示一个标识的作用
 *
 *  5、如果注解有成员 在使用自定义的注解时需要给成员赋值,如果有了默认值就可以不用了
 *     但是不想用默认值可以自己重新的赋值
 *     @MyAnotation("hi")
 *
 * 二、元注解(对现有注解进行修饰的注解,jdk自带的)有4个
 *   1) @Target(ElementType.METHOD) 用来说明当前自定义的注解能修饰那些元素,类? 属性? 还是方法等
 *       TYPE 类、接口、枚举类
 *       LOCAL_VARIABLE 局部变量
 *
 *   2)  @Retention(RetentionPolicy.SOURCE)  指定 注解的生命周期
 *     SOURCE 是编译阶段存在 编译好了就没有 注解了
 *     CLASS  在.class 文件里面存在,但是不会加载到内存里面,默认值
 *     RUNTIME 会加载到内存里可以通过反射的方式获取到,进而判断注解是干啥的
 *
 *   3) @Documented 表示所修饰的注解在被javadoc 解析时会保留
 *
 *   4)@Inherited 他修饰的注解类将具有继承性,如果某个类使用我们自定义的注解那么这个类的子类也具有该注解
 *
 *  三、通过反射来获取注解信息
 *
 *        Class clazz = Student.class;
 *        Annotation[] annotations = clazz.getAnnotations();
 *
 *        for (int i = 0; i < annotations.length; i++) {
 *          System.out.println(annotations[i]);
 *        }
 *
 *  四、jdk 8 新特性中的注解
 *
 *     1)可重复注解
 *
 *
 *  五、自定义注解的使用场景
 *
 *     实现自定义注解+拦截器,自定义注解+AOP
 *
 *  六、类型注解
 *
 *     注解修饰范型、异常、基本变量
 *
 *
 */

 

2、创建自定义注解

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE,METHOD,FIELD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})
public @interface MyAnotation {

    String value() default "hello"; //注意这里是成员属性,并提供默认的值
}

2.1 创建属性是数组的自定义注解

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface RountingInjected {
    /**
     *
     * 如果注解有成员 在使用自定义的注解时需要给成员赋值,如果有了默认值就可以不用了
     * 但是不想用默认值可以自己重新的赋值
     * @return
     */
    String value() default "helloServiceImpl1";

    /**
     *  注解成员为数组,别名是value,在使用自定义的注解时需要给成员赋值,如果有了默认值就可以不用了
     *  value={"",""}
     * @return
     */
    @AliasFor("value")
    String[] locations() default {};

}

 

3、注解配合拦截器实现权限的控制

3.1 创建一个interceptor

public class SourceAccessInterceptor implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("进入拦截器了");

        // 反射获取方法上的LoginRequred注解
        HandlerMethod handlerMethod = (HandlerMethod)handler;
        MyAnotation myAnotation = handlerMethod.getMethod().getAnnotation(MyAnotation.class);
        if(myAnotation == null){
            return true;
        }

        // 有LoginRequired注解说明需要登录,提示用户登录
        response.setContentType("application/json; charset=utf-8");
        response.getWriter().print("你访问的资源需要登录");
        return false;

    }


    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }


    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

3.2 创建配置类把拦截器添加到拦截器链中

@Configuration
public class InterceptorTrainConfigurer implements WebMvcConfigurer {

    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SourceAccessInterceptor()).addPathPatterns("/**");
    }
}

3.3 使用自定义注解

   @MyAnotation
    @RequestMapping("/hello1")
    @ResponseBody
    public String hello1(){

        String name =  myService.sayHello("tomcat");
        System.out.println(name);
        return name;
    }

3.4 效果

4、可重复注解

意思是 同样的自定义注解在一个元素上可以用两次

/**
 *
 *  jdk8 之前的写法 @MyAnotations({@MyAnotation("h"),@MyAnotation("h2")})
 *
 *  jdk8 之后的可以这样写 在  1、MyAnotation 上加一个元注解 @Repeatable 成员值是 MyAnotations.class
 *                         2、MyAnotation 的 @Inherited @Retention 以及  @Target 要和 MyAnotations 一致
 *
 */
//@MyAnotations({@MyAnotation("h"),@MyAnotation("h2")})
@MyAnotation("h2")
@MyAnotation("h3")
@Component
public class Yellow {

    private int num = 1;

    public void get(){
        System.out.println("=======yellow=======");
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    @Override
    public String toString() {
        return "Yellow{" +
                "num=" + num +
                '}';
    }
}

 5、类型注解

/**
 *
 *  类型注解 两个 TYPE_USE,TYPE_PARAMETER JDK8 以后才有的
 *  注解修饰范型、修饰别的地方
 *
 *
 *
 *
 * @param <T>
 */
public class GenericF<@MyAnotation T> {


    public void shows() throws @MyAnotation RuntimeException{
        ArrayList<@MyAnotation String> list = new ArrayList<>();
        int num = (@MyAnotation int)10L;
    }


}

  

posted on 2021-06-20 18:31  与时具进&不忘初心  阅读(218)  评论(0编辑  收藏  举报