Java 注解 (Annotation) 三类注解 编译器使用到的注解 @Override,@SuppressWarnings都是编译器使用到的注解,作用是告诉编译器一些事情,而不会进入编译后的.class文件
.class文件使用到的注解 需要通过工具对.class字节码文件进行修改的一些注解,某些工具会在类加载的时候,动态修改用某注解标注的.class文件,从而实现一些特殊的功能,一次性处理完成后,并不会存在于内存中,都是非常底层的工具库、框架会使用,对于开发人员来说,一般不会涉及到
运行期读取的注解 一直存在于JVM中,在运行期间可以读取的注解,也是最常用的注解,如Spring的@Controller,@Service,@Repository,@AutoWired,Mybatis的@Mapper,Junit的@Test等,这类注解很多都是工具框架自定义在运行期间发挥特殊作用的注解,一般开发人员也可以自定义这类注解。
###定义Annotation
使用@interface来定义一个注解 1 2 3 4 5 6 7 8 9 10 public @interface Table { String value () default "" ; } public @interface Colum { String value () default "" ; String name () default "" ; String dictType () default "" ; }
注解主要用到了String类型,但实际上还可以是基本数据类型(不能为包装类)、枚举类型。
约定俗成: 最常用的参数应该命名为value,同时一般情况下我们都会通过default参数设置一个默认值。
元注解 可以修饰注解的注解即为元注解,Java已经定义了一些元注解,我们可以直接使用
可以使用元注解来修饰注解,元注解包括多个,必须设置@Target和@Retention,@Retention一般设置为RUNTIME。
@Target 指定注解使用的目标对象,参数为ElementType[]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 public @interface Target { ElementType[] value(); } public enum ElementType { TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE, TYPE_PARAMETER, TYPE_USE }
ElementType.PACKAGE
1 2 3 4 5 @Target(ElementType.PACKAGE) public @interface Table { String value () default "" ; }
需要 创建package-info.java文件
1 2 3 4 5 6 7 @Table package annotation;class PackageInfo { public void hello () { System.out.println("hello" ); } }
还可以自行了解下 ElementType.TYPE_PARAMETER和ElementType.TYPE_USE* @Retention 用于定义注解的生命周期,参数为枚举RetentionPolicy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Retention { RetentionPolicy value () ; } public enum RetentionPolicy { SOURCE, CLASS, RUNTIME }
@Documented 表示是否将此注解的相关信息添加到javadoc文档中
@Inherited 该注解和子类的关系,使用此注解声明出来的自定义注解,在使用在类上面时,子类会自动继承此注解,否则,子类不会继承此注解。注意,使用@Inherited声明出来的注解,只有在类上使用时才会有效,对方法,属性等其他无效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Person { String value () default "man" ; } @Person public class Parent {} class Son extends Parent {}
Annotation处理 注解定义后也是一种class,所有的注解都继承自java.lang.annotation.Annotation,因此,读取注解,需要使用反射API。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Colum { String value () default "" ; String name () default "" ; } public class Person { @Colum(name = "姓名") private String name; @Colum(name = "性别") private String gender; @Colum(name = "年龄") private int age; @Colum(name = "住址") private String address; public String getName () {return name;} public void setName (String name) {this .name = name;} public String getGender () {return gender;} public void setGender (String gender) {this .gender = gender;} public int getAge () {return age;} public void setAge (int age) {this .age = age;} public String getAddress () {return address;} public void setAddress (String address) {this .address = address;} } public static void main (String[] args) throws ClassNotFoundException { List<String> columNames = new ArrayList <>(); Class clazz = Class.forName("annotation.Person" ); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields){ Colum colum = field.getAnnotation(Colum.class); field.isAnnotationPresent(Colum.class); columNames.add(colum.name()); } columNames.forEach((columName) -> System.out.println(columName)); }