自定义注解的理解和使用
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;
}
}
浙公网安备 33010602011771号