一文读懂Lombok原理( 二 )


接下来我们演示一下如何用 APT工具生成一个class文件,然后我们再说 Lombok是如何修改已存在的类中的属性的 。
定义注解【一文读懂Lombok原理】首先当然我们需要定义自己的注解了
@Retention(RetentionPolicy.SOURCE) // 注解只在源码中保留@Target(ElementType.TYPE) // 用于修饰类public @interface GeneratePrint {String value();} 
Retention注解上面有一个属性value,它是 RetentionPolicy类型的枚举类,RetentionPolicy枚举类中有三个值 。
public enum RetentionPolicy {SOURCE,CLASS,RUNTIME} 

  • SOURCE修饰的注解:修饰的注解,表示注解的信息会被编译器抛弃,不会留在class文件中,注解的信息只会留在源文件中
  • CLASS修饰的注解:表示注解的信息被保留在class文件(字节码文件)中当程序编译时,但不会被虚拟机读取在运行的时候
  • RUNTIME修饰的注解:表示注解的信息被保留在class文件(字节码文件)中当程序编译时,会被虚拟机保留在运行时 。所以它能够通过反射调用,所以正常运行时注解都是使用的这个参数
Target注解上面也有个属性value,它是 ElementType类型的枚举 。是用来修饰此注解作用在哪的 。
public enum ElementType {TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE,TYPE_PARAMETER,TYPE_USE} 
定义注解处理器我们要定义注解处理器的话,那么就需要继承 AbstractProcessor类 。继承完以后基本的框架类型如下
@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方法:在编译时,编译器执行的方法 。也就是我们写具体逻辑的地方
我们是演示一下如何通过继承 AbstractProcessor类来实现在编译时生成类,所以我们在 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;}


推荐阅读