1 注解的简单实现
1、定义注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ParamValue {
String value() default "";
}
2、使用注解
public class Person {
@ParamValue(value="tutu")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3、解析注解
Person person = new Person();
Field field = Person.class.getDeclaredField("name");
ParamValue annotation = field.getAnnotation(ParamValue.class);
String name = annotation.value();
person.setName(name);
System.out.println(person.getName());
2 注解的细节和理解
2.1 注解的组成以及它们的作用
1)@Document
主要作用:在生成javadoc文件时,修饰所用的代码会展现出来,通俗讲就是@ParamValue(value="tutu")会展示在doc中,反之如果ParamValue不加@Document注解则不会将这句代码展示出来。
2)@Retention
- SOURCE:作用于编译期间,例如Override注解,也可以配合AbstractProcessor实现自定义的注解处理器来处理,并且在生成class文件之前对代码进行处理。
- CLASS:作用于class代码生成后和类加载之前,通过实现AbstractProcessor自定义注解处理器,可以修改class文件,并且在class文件中添加更多标识,比如可以对每个字段自动添加set和get方法。
- RUNTIME:作用于运行期间,一般用于自定义参数对属性进行标记,在主函数中依赖反射机制识别注解并进行处理,例如Spring中的Component等。
3)@Target
主要作用:限定注解使用范围。
4)@Inherited
主要作用:使得子类继承父类的注解,当注解被@Inherited所标记时。
2.2 对注解的思考和拓展
1、注解类型中的编译时和运行时在执行方式上有什么不同
编译时的注解更多的采用APT的方式处理,使用AbstractProcessor在编译期利用java代码生成java代码,然后将新的java文件和旧的java文件一同被javac所编译来处理,而运行时的注解更多采用反射的方式处理
2、对编译时注解和运行时注解在使用方式上的理解
编译时注解的使用方向上更倾向于修改代码或者对用户进行无感知的代码或者版本检测,例如利用apt方式加javapoet工具就可以在编译期实现便捷的代码模块化的生成,在我们项目中需要不停的生产crud代码时可以通过自定义多个注解,然后通过这些注解所传入的参数达到对crud代码定制化生成的功能,运行时注解的使用方向更倾向于修改对象,所以在自动化配置方面所实现的注解基本都是运行时。