Retention注解上面有一个属性value,它是RetentionPolicy类型的枚举类,RetentionPolicy枚举类中有三个值 。
public enum RetentionPolicy {SOURCE,CLASS,RUNTIME}
- SOURCE修饰的注解:修饰的注解,表示注解的信息会被编译器抛弃,不会留在class文件中,注解的信息只会留在源文件中
- CLASS修饰的注解:表示注解的信息被保留在class文件(字节码文件)中当程序编译时,但不会被虚拟机读取在运行的时候
- RUNTIME修饰的注解:表示注解的信息被保留在class文件(字节码文件)中当程序编译时,会被虚拟机保留在运行时 。所以它能够通过反射调用,所以正常运行时注解都是使用的这个参数
public enum ElementType {TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE,TYPE_PARAMETER,TYPE_USE}定义注解处理器我们要定义注解处理器的话,那么就需要继承AbstractProcessor类 。继承完以后基本的框架类型如下 。推荐一个 Spring Boot 基础教程及实战示例:
https://github.com/javastacks/spring-boot-best-practice
@SupportedSourceVersion(SourceVersion.RELEASE_8)@SupportedAnnotationTypes("aboutjava.annotion.MyGetter")public class MyGetterProcessor extends AbstractProcessor {@Overridepublic synchronized void init(ProcessingEnvironment processingEnv) {super.init(processingEnv);}@Overridepublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {return true;}}我们可以看到在子类中上面有两个注解,注解描述如下- @SupportedSourceVersion:表示所支持的Java版本
- @SupportedAnnotationTypes:表示该处理器要处理的注解
- init方法:主要是获得编译时期的一些环境信息
- process方法:在编译时,编译器执行的方法 。也就是我们写具体逻辑的地方
如下所示 。
@Overridepublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {StringBuilder builder = new StringBuilder().Append("package aboutjava.annotion;nn").append("public class GeneratedClass {nn") // open class.append("tpublic String getMessage() {n") // open method.append("ttreturn "");// for each javax.lang.model.element.Element annotated with the CustomAnnotationfor (Element element : roundEnv.getElementsAnnotatedWith(MyGetter.class)) {String objectType = element.getSimpleName().toString();// this is appending to the return statementbuilder.append(objectType).append(" says hello!\n");}builder.append("";n") // end return.append("t}n") // close method.append("}n"); // close classtry { // write the fileJavaFileObject source = processingEnv.getFiler().createSourceFile("aboutjava.annotion.GeneratedClass");Writer writer = source.openWriter();writer.write(builder.toString());writer.flush();writer.close();} catch (IOException e) {// Note: calling e.printStackTrace() will print IO errors// that occur from the file already existing after its first run, this is normal}return true;}定义使用注解的类(测试类)上面的两个类就是基本的工具类了,一个是定义了注解,一个是定义了注解处理器,接下来我们来定义一个测试类(TestAno.java) 。我们在类上面加上我们自定的注解类 。@MyGetterpublic class TestAno {public static void main(String[] args) {System.out.printf("1");}}这样我们在编译期就能生成文件了,接下来演示一下在编译时生成文件,此时不要着急直接进行javac编译,MyGetter类是注解类没错,而MyGetterProcessor是注解类的处理器,那么我们在编译TestAnoJava文件的时候就会触发处理器 。因此这两个类是无法一起编译的 。先给大家看一下我的目录结构
aboutjava-- annotion-- MyGetter.java-- MyGetterProcessor.java-- TestAno.java所以我们先将注解类和注解处理器类进行编译javac aboutjava/annotion/MyGett*接下来进行编译我们的测试类,此时在编译时需要加上processor参数,用来指定相关的注解处理类 。javac -processor aboutjava.annotion.MyGetterProcessor aboutjava/annotion/TestAno.java大家可以看到动态图中,自动生成了Java文件 。
推荐阅读
- 一文带你了解 「图数据库」Nebula 的存储设计和思考
- 去哪儿网MySQL日志分析实践,80%数据丢失都给你救回来
- 春季预防流感小常识 你都做对了吗
- 春季男性如何养生 这些养生小常识能帮你
- 春季怎么养肝护肝 老中医教你六个护肝秘方
- 天鹅颈|天鹅颈是好气质的加分项,刘诗诗倪妮太迷人,脖颈护理你更得重视
- 雕刻|工匠雕刻翡翠的时候,心里面都在想什么?我来帮你分析一下
- 中小学生都要学做饭了,你还分不清五谷是啥?
- 其实你并不会用微信,盘点微信上隐蔽却超实用的功能
- 微信NFC功能你知道吗?
