Lombok经常用,它是怎么生成代码的呢?

  1. Spring框架中@Controller、@Service等等这类注解都是运行时注解,运行时注解大部分都是通过反射来实现的。而Lombok是使用编译时注解实现的。编译时注解和运行时注解各是什么呢?
  2. Java中的注解分为运行时注解和编译时注解,运行时注解就是我们经常使用的在程序运行时通过反射得到我们注解的信息,然后再做一些操作。而编译时注解是什么呢?就是在程序在编译期间通过注解处理器进行处理。编译期:Java语言的编译期是一段不确定的操作过程,因为它可能是将*.java文件转化成*.class文件的过程;也可能是指将字节码转变成机器码的过程;还可能是直接将*.java编译成本地机器代码的过程运行期:从JVM加载字节码文件到内存中,到最后使用完毕以后卸载的过程都属于运行期的范畴。

  3. 注解处理工具apt(Annotation Processing Tool) 正常情况下使用APT工具只是能够生成一些文件(不仅仅是我们想象的class文件,还包括xml文件等等之类的),并不能修改原有的文件信息,Lombok是修改了Java中的**抽象语法树AST**才做到了修改其原有类的信息。

  4. Processor就是用于处理编译器注解的类。通过继承AbstractProcessor就可以自定义处理注解

  • init(ProcessingEnvironment processingEnvironment):初始化方法,这个方法会被注解处理 工具 调用,并传入一个ProcessingEnvironment变量,这个变量非常重要,它会提供一些非常使用的工具如Elements, Filer, Messager,Types等,后面我们会单独介绍它们。

  • getSupportedOptions: 这个方法允许我们自定义一些参数传给Processor,

  • getSupportedAnnotationTypes: 这个方法用于注解的注册,只有在这个方法中注册过的注解才会被注解处理器所处理

  • getSupportedSourceVersion:返回你目前使用的JDK版本,通常返回SourceVersion.latestSupported(),当然如果你没使用最新的JDK版本的话,也可以返回指定版本

  • process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment):这个方法是Processor中最重要的方法,所有关于注解的处理和文件的生成都是在这个方法中完成的。它有两个参数,第一个Set<? extends TypeElement> set包含所有待处理的的注解,需要注意的是,如果你定义了一个注解但是没有在代码中使用它,这样是不会加到set中的。第二个参数roundEnvironment表示当前注解所处的环境,通过这个参数可以查询到当前这一轮注解处理的信息。第一个参数我们通常用不到它,最常用的是roundEnvironment中的getElementsAnnotatedWith方法,这个方法可以返回被特定注解标注的所有元素。process方法还有一个boolean类型的返回值,当返回值为true的时候表示这个Processor处理的注解不会再被后续的Processor处理。如果返回false,则表示这些注解还会被后续的Processor处理,类似拦截器模式。

  • Processor接口中定义了注解处理器中必要的方法,AbstractProcessor是实现Processor接口的一个抽象类,它在Processor的基础上提供了三个个注解功能,分别对应上面的三个方法。从下图中的名字也很容易看出对应的哪些方法。

  • Java注解ä¹ç¼è¯æ¶æ³¨è§£

  • 所有被注解标注的部分都会被解析成element,在上面介绍的process方法中,通过roundEnvironment的getElementsAnnotatedWith方法就可以获取到element的set,element既可能是类,也可能是类属性,还可能是方法

  • 所有被注解标注的部分都会被解析成element,在上面介绍的process方法中,通过roundEnvironment的getElementsAnnotatedWith方法就可以获取到element的set,element既可能是类,也可能是类属性,还可能是方法

  • Java注解ä¹ç¼è¯æ¶æ³¨è§£

  • element类型和修饰注解用途【@Target(ElementType.TYPE)】的对比

  • 拿到对应Element之后,还需要收集Element的相关信息,下面我们介绍几个常用的方法

  • getSimpleName:获取该元素的名字

  • getModifiers:获取该元素的访问权限,返回一个Set

  • asType: 获取该元素的类型,比如TextView会返回android.widget.TextView

  • getEnclosingElement:获取父级元素,比如参数的父级是方法,方法的父级是类或者接口。

  • getEnclosedElements: 这个和上面的方法是对应的,获取当前元素的一级子级元素列表。

  • ProcessingEnvironment类

  • getLocale:返回Locale对象,这个没什么可说的,就是国际化的东西

  • getSourceVersion:支持的Java版本

  • getOptions:这个在上面介绍getSupportedOptions有用到过,就是用来接收外部参数的

  • getMessager:返回一个Messager对象,Messager是一个分等级的log工具,一共分为 NOTE,WARNING,MANDATORY_WARNING,ERROR,OTHER 五个等级。实际上在Processor中我们也可以使用sout的方式打印信息,我们可以通过一段代码测试它们之间的区别

  • getElementUtils:返回一个Elements对象,和Element相关的工具类。比如我们要获取包名怎么办?可以通过上面介绍过的getEnclosingElement方法一层一层网上找,非常麻烦也很容易出错。还可以通过Elements中的getPackageOf方法直接获取到

  • getTypeUtils:返回一个Types对象,和元素类型相关的工具类

  • getFiler:返回一个Filer对象,负责生成文件,里面的方法很少只有4个,我们要生成java文件的时候就调用createClassFile方法就可以了。

实战

先编译 javac  compileTimeAnnotation/lombok/MyGett*

 

 

再执行javac -processor     compileTimeAnnotation.lombok.MyGetterProcessor    compileTimeAnnotation/lombok/TestAno.java

 

 

参考:

https://mp.weixin.qq.com/s/qde6zvqbE84gDcw_zEo62g

https://www.codercto.com/a/92257.html

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值