赞
踩
这段时间,做了很多开发效率相关的事情,涉及到了不少代码生成的方法和思路,总结如下。生成代码分两部分:代码分析生成工具和代码模板
按编写难度排序
这个是intellij的一个简单工具,看起来就是对freemarker或者正则替换做了一些封装。代表方案当然就是内置的那些了。
创建很简单:https://www.jetbrains.org/intellij/sdk/docs/tutorials/live_templates/template_support.html
值得注意的是,可以在 Edit variables的地方指定更复杂的匹配,生成更丰富的代码。
这种方案的优点:
缺点:
代表方案是GreenDao。
生成代码的流程是独立于App编译过程的。即有一个Java console的main方法,执行这个方法,能够根据config在指定位置生成代码。如果要将这个融入到编译过程中,需要用gradle task 在所有编译前调用jar包。
GreenDao比较巧妙的使用了Java代码作为Config文件,大大简化了代码生成工具的复杂程度。在时机生成过程中,可以使用json、xml等作为配置文件(Spring模式),与写代码区别并不大,只是免去了复杂工具的编译时间。
这种方案的优点:
缺点:
这是目前最常见的方案,个人感觉ButterKnife和Android annotation可以作为代表。
生成代码的流程是Java编译内置的hook点,安全性和兼容能力非常强。Java本身提供了javax.lang.model的整套代码分析体系,能够非常好的对现有代码进行分析。然而其中的element和typemirror之间的转换、类名获取这种事情非常容易被搞晕。
整个工具编写比较简单:tutorial。但是一旦出现正向(怎么做xxx)问题,很难找到know-how的人。反向问题(bug)的调试反而非常简单,因为生成的代码都是可见且可断点的(不能修改)。
apt能做的东西,个人理解有几种:生成boilerplate代码,ButterKnife这种;以编译期生成代码减少反射,EventBus 3.0的Subscriber Index,后面我还会开源一个无反射按field名读取值的apt工具;类的合法性校验,这个是只有apt才能做的。
这种方案的优点:
缺点:
这是个通用技术,虽然顶着AOP的帽子,很多时候也会被用来生成代码。Hugo是个非常好的例子,有一个通用的plugin在Android工程下使用AspectJ,而切面又非常简单,好懂。
本身文档还比较完整,只是index比较乱。具体的hook,应该是基于gradle plugin的(没细致研究过)。底层是基于ASM的,成熟没什么兼容性问题。对于现有类的分析基本靠固定的匹配机制,更多的是依赖字符串和正则,不容易分析更深层次的类行为(人家本来就是用来做切面定义的),而且对于切面来说,能够拿到的上下文信息比较受限。
对于扩展信息,多是基于不适用Android的aspectj language,比较头疼。
这种方案的优点:
缺点:
Javassist是改代码的工具里最接近apt的。有个实例工程可以拿来当模板。
文档有,但比较有用的仅限于官方的tutorial,文档内容丰富程度堪比javax.lang.model,完全看不懂。想要嵌入打包过程,必须自己写plugin和transform,里面的坑也不少,资料也不多。而对于类的匹配和遍历都是需要手动写,远远高于apt的复杂程度。当然,真正处理也是复杂一些。Groovy语言本身,也是一大槽点,编的时候什么都能过,运行的时候什么都挂。主要的优势在于全能修改类和无视依赖关系两项。
这种方案的优点:
缺点:
ASM就是究极超神方案了,直接搞bytecode。仅仅看懂了某个开源项目。也需要手写plugin和transform,和javassist的区别主要在于代码形式和对代码的遍历方式(tree visitor vs structured object)。过多的做评述。
专门做代码分析的,待补充。
仅在极简单或没有模板可用的时候用,否则就是自作孽。
通用技术,没有对java的优化。
优点:
缺点:
针对Java生成的专门库,对于import、替换有非常好的支持。
优点:
缺点:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。