KAPT(Annotation Processing for Kotlin)是什么

什么是APT?

Annotation Processing Tool官方称其为Pluggable Annotation Processing API(可插入式注解处理API?),在06年的Java规范JSR-269中提供了一套标准API来处理Annotation(JSR-175),这里提到的注解不是在运行时通过反射机制运行处理的注解,而是在编译时处理的注解。其实就是javac提供的一个工具,用来在编译时期去扫描处理注解信息,它把Java语言中众多元素(如method、type、enum等)映射为Types和Elements,然后把这些扫描到的信息提供给Annotation Processor进行处理,编译器每次执行完process()方法就算是一个“round”结束,如果一个“round”结束后有新的代码生成,编译器会继续调用Annotation Processor,直到没有新代码生成为止。
其实就是Java提供了一个编译插件,允许我们通过这个插件在程序编译时生成一些代码,并且执行生成的代码将会与你手动编写的代码一起被javac编译!!

Annotation Processor执行流程.png

什么是KAPT?

kpat--Kotlin Annotation Processing,顾名思义,就是服务于Kotlin的Annotation Processing,Kotlin M12版本中发布了kapt1,在这之前,Kotlin的官方Blog中提到JetBrains团队在考虑支持Annotation Processing时提出了3种解决方案:

  1. 为Kotlin重新实现一套JSR-269API,但这样做就只支持Kotlin项目了,使用这种方案明显不合理,而且也与“Kotlin可以完美与现有Java项目共存”相违背。
  2. 从Kotlin源码中生成Java源码,也就是将你的Kotlin代码逻辑给翻译成可执行的Java代码,并将它们加入到javac的classpath中,最后运行注解处理器,这种方案带来的工作量和难度是巨大的;不过另一种基于JVM的语言Groovy已经有另一种解决方案,就是生成"存根类",这个类里面所有方法的方法体为空,也就是只保留类的结构,然后把这些"存根类"加入javac classpath中编译,这种解决方案的一个优点是让引用注解处理器生成的类成为可能,但是这种解决方案也存在一些问题,比如说有很多时候方法的返回类型是需要对表达式进行分析,并且生成这些"存根类"要解决项目中所有的声明,这将会大大降低编译速度。
    解决方案2.png
  3. 简单来说就是将Kotlin代码编译成Java编译器可识别的二进制文件,在Java编译器把扫描的注解信息交给Processor执行之前,Kotlin编译器会注入其扫描的注解信息。但是由于在一开始Kotlin就已经将代码编译好,所以代码无法引用Processor生成的类,而且仅在源文件中保留的注解(RetentionPolicy.SOURCE)将被忽略。

解决方案3.png

JetBrains团队最终采取第3种方案实现了kapt1,如上所说,这种实现方案最大的一个限制就是Kotlin代码引用不了Processor生成的代码,生成这些不被引用的代码有什么用?当然,你可以事先定义好这些生成类的路径与方法名然后在源码中通过反射去调用(手动滑稽。因此,随后发布的版本中JetBrains团队做了一些优化:生成源码的"存根类"以支持对生成代码的引用;当然上面提到的问题依然没有解决,只是把生成"存根类"作为可选配置由用户自己决定是否使用该功能而已,而且这种对生成代码的引用并不完美:虽然生成的"存根类"中没有方法体,所以方法体内对尚未生成的代码进行引用不会报错,但是方法签名中如果包含了对这些代码的引用(参数类型或者返回类型),最终Processor生成的Java代码中会引用一些不存在的类从而导致编译器报错(unresolved reference)。
后来相继推出了kapt2以及kapt3,kapt2通过包装Intellij平台的抽象语法树实现了JSR-269来克服上面提到的限制,但是Intellij平台没有针对这些实现进行优化,导致某些时候注解处理器可能会非常慢;kapt3替代了kapt2的实现,直接从Kotlin代码生成javac的Java AST,后面的步骤直接走javac原本的流程即可。
到目前为止kapt3已经解决上面提到的大部分问题,但仍然存在一些不太友好的地方,比如使用kapt3生成了Kotlin代码在AndroidStudio中是不会加入到Kotlin编译器中编译的,需要自己在build.gradle中配置类似下面这样的代码

afterEvaluate {
    android.applicationVariants.all { variant ->
        if (variant.buildType.name == 'debug') {
            def kotlinGenerated = file("$buildDir/generated/source/kaptKotlin/${variant.name}")
            variant.addJavaSourceFoldersToModel(kotlinGenerated)
            return
        }
        ...
    }
}

而且在Processor中打印的NOTE级别日志也没有输出到控制台中,调试的时候非常不方便,debug还要求你手速要快- -!(debug方式参考这里
总的来说,现在Kotlin对Annotation Processing的支持除了存在一些小问题,总体上还是不错的,期待JetBrains团队后续的优化

参考链接:
官方博客相关文章:https://blog.jetbrains.com/kotlin/2015/05/kapt-annotation-processing-for-kotlin/
https://blog.jetbrains.com/kotlin/2015/06/better-annotation-processing-supporting-stubs-in-kapt/
Medium相关文章:https://medium.com/@workingkills/pushing-the-limits-of-kotlin-annotation-processing-8611027b6711
https://medium.com/@daptronic/annotation-processing-with-kapt-and-gradle-237793f2be57

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342