JDK源码 -- 自定义注解

版权声明:转载原创博客请附上原文链接 https://blog.csdn.net/weixin_43495590/article/details/89488344

一:构建注解

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface TestAnnotation {

    int number() default 1;
    
    String  value () default "ceshi";
    
}
1.1 关键字

关键字采用@interface

1.2 基注解

注解可以使用四大基类注解进行构建,分别代表作用域、保存位置、是否加入javadoc、是否可以被子类继承等。同时注解也可以加上其它定义注解,拥有与其相同的效果

1.3 方法

注解中包含的方法就是使用时注入的属性,类型 + 名字 + [默认值]构成,注意一点就是参数类型不能是包装类

二:基类注解详解

2.1 @Target
// 加入javadoc文件
@Documented
// 运行时也可以获取到注解信息
@Retention(RetentionPolicy.RUNTIME)
// 注解只能定义在注解上
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    ElementType[] value();
}
  • 作用:标记注解作用范围
  • 属性值:value属性的属性值为ElementType枚举类数组
public enum ElementType {
	// 类
    TYPE,  
    // 属性                   
    FIELD, 
    // 方法		             
    METHOD,       
    // 参数           
    PARAMETER,    
    // 构造器           
    CONSTRUCTOR, 
    // 局部变量           
    LOCAL_VARIABLE, 
    // 注释类型        
    ANNOTATION_TYPE,      
    // 包  
    PACKAGE,              
	// JDK1.8新增用以注解类型
    TYPE_PARAMETER, 
    TYPE_USE
}
2.2 @Retention
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    RetentionPolicy value();
}

  • 作用:标记有效时间
  • 属性值:value属性的属性值为RetentionPolicy枚举对象
public enum RetentionPolicy {
	// class文件不可见
    SOURCE,
    // 运行时不可见
    CLASS,
    // 运行时可见,通过反射得到注解信息
    RUNTIME
}
2.3 @Document
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
  • 作用:理解为标记型注解,被注释内容会被javadoc提取保存
2.4 @Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
  • 作用:标记型接口,标记该注解是否能被子类继承

三:注解使用

3.1 基本使用

根据基类注解Target标记作用范围在相应地方使用即可,注意一点就是如果注解有多个属性务必要显示声明属性名

3.2 反射操作注解

就随便玩了一下,反正和普通的方法、属性反射操作没有区别

@TestAnnotation(value = "111",number = 123)
public class Test {
    
    public static void main(String[] args) {
        Annotation[] annotations = Test.class.getAnnotations();
        Arrays.stream(annotations).forEach(annotation -> {
            if (annotation instanceof TestAnnotation){
                TestAnnotation ta = (TestAnnotation)annotation;
                int number = ta.number();
                String value = ta.value();
                System.out.println(number + value);
            }
        });
    }
    
}

四:@RepeatTable

注解重复使用,例如定义一个学生注解@Student,在班级测试类上需要注解@Student标记所有学生,班级学生有多个需要使用到多次@Student。这时候就需要在@Student上注解@RepeatTable记录所有的@Student注解属性值

// 定义学生集合注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Students {
    Student[] value();
}

//  定义学生注解,使用Students注解容器
@Repeatable(value = Students.class)
public @interface Student {
    String name();
}

// 多次使用Student学生注解
// 获取Test类注解查看信息
@Student(name = "zhangsan")
@Student(name = "lisi")
@Student(name = "zss")
public class Test {

    public static void main(String[] args) {
        Student[] student = Test.class.getAnnotation(Students.class).value();
        Arrays.stream(student).forEach(s -> System.out.println(s.name()));
    }

}

猜你喜欢

转载自blog.csdn.net/weixin_43495590/article/details/89488344