静态编译下Groovy扩展方法兼容方案及同项目实现问询
Groovy扩展方法与@CompileStatic兼容性:项目内直接实现方案
咱们先把几种常见扩展方式和@CompileStatic的兼容情况理清楚,再重点解决你关心的「同一项目内直接定义支持静态编译的扩展方法」问题:
一、各扩展方式的静态编译兼容性
- 元类(meta-class):完全不兼容。元类是靠运行时动态修改类行为实现的,而静态编译是提前绑定方法、做类型检查,编译器根本识别不了运行时的元类修改,用了肯定报错。
- 类别(categories):勉强能用但限制多。必须把调用代码包在
use()块里,而且静态编译下得显式导入类别类,没法像全局扩展那样直接调用,灵活性很差。 - 扩展模块(extension modules):完美兼容,这也是你提到的预构建jar能生效的原因。但你想在同一个项目里直接定义,不用提前打包jar?完全可以!
二、同一项目内直接实现支持@CompileStatic的扩展方法
Groovy支持这种玩法,步骤很简单,不用额外打包操作:
- 写扩展类:创建普通的Groovy/Java类,所有扩展方法都是静态方法,第一个参数必须是你要扩展的类型(比如
String),剩下的是方法参数。举个例子:
package com.yourteam.utils class StringExtensions { // 给String扩展一个反转并转大写的方法 static String reverseAndUppercase(String self) { self.reverse().toUpperCase() } }
- 加扩展模块描述文件:在项目的
src/main/resources/META-INF/services目录下,新建一个名为org.codehaus.groovy.runtime.ExtensionModule的文件,内容填这些:
moduleName=my-project-string-extensions moduleVersion=1.0 extensionClasses=com.yourteam.utils.StringExtensions
记得把com.yourteam.utils.StringExtensions换成你自己扩展类的全限定名,多个扩展类可以用逗号分隔。
3. 在静态编译类里直接用:现在标注@CompileStatic的类就能直接调用这个扩展方法了,和用预构建jar完全一样:
@CompileStatic class TestExtensionUsage { static void main(String[] args) { String testStr = "hello groovy" println testStr.reverseAndUppercase() // 输出 YVOORG OLLEH } }
三、几个要注意的细节
- 扩展类里的方法必须是静态的,第一个参数的类型就是你要扩展的类,参数名一般用
self或者delegate来标识,方便阅读。 - 扩展模块描述文件的格式不能错,每个属性单独占一行,别写错键名(比如
extensionClasses不能拼错)。 - 如果是多模块项目,要确保描述文件和扩展类在同一个模块的类路径里,或者其他模块能依赖到这个模块。
内容的提问来源于stack exchange,提问作者Werner Thumann
相关产品推荐
相关产品推荐

