GEP-9
摘要:模块化
此 GEP 介绍了模块化工作背后的目标和建议细节,该工作将
-
为核心 Groovy 提供更精简的 jar 文件,其他 jar 文件包含可能被认为是 Groovy 可选部分的内容
-
为 Groovy 库编写者提供与 Groovy 运行时的挂钩,以允许他们以各种方式扩展 Groovy - 允许 “grapes” 更像插件而不是传统库
-
有关模块化如何影响其他工件的辅助细节,例如 Groovy 构建、维基、jira 组件等。
此活动建立在之前讨论过的工作基础上:Groovy 2.0 模块化以及稍早的配置文件讨论打包和模块化。
范围之外
虽然我们应该密切关注其他模块化工作,但在现阶段,我们预计 Groovy 类将发生结构性变化,这些变化与最终使用 OSGi 或 Java 8 的 Jigsaw 模块化无关。
Jar 分组
目前,Groovy 提供两个主要的 jar 工件
-
groovy.jar 包含 Groovy 的核心类,并且依赖于一小部分关键的依赖 jar 文件(即 asm、antlr 等)
-
groovy-all.jar 包含 Groovy 的核心类以及捆绑的版本的关键依赖 jar 文件
模块化后,主要的 Groovy 代码库将打包到额外的 jar 工件中
-
groovy.jar 或 groovy-core.jar(名称待定)将包含更少的 Groovy 核心类,并将保留对其依赖于一小部分关键依赖 jar 文件(即 asm、antlr 等)的依赖
-
许多较小的“模块/组件”jar 文件(确切的名称/数量/内容待定),但可能是诸如 groovy-bsf.jar、groovy-sql.jar、groovy-swing.jar、groovy-jmx.jar、groovy-xml、groovy-tools 等等
-
groovy-all.jar 包含 Groovy 的核心类、捆绑版本的关键依赖 jar 文件以及模块 jar 文件中的所有类
-
我们可能会选择支持其他“配置文件” - 配置文件是我们捆绑在一起用于其他环境的其他“胖” jar 文件,例如 groovy-android.jar 可能排除 JMX 或 Swing 模块。
欢迎您对 jar 分组提出建议/意见。在随附的讨论中查看更多细节:Groovy 2.0 模块化。
此捆绑工作的目标之一是通过以下方式促进 Groovy 作为一种语言的演变
-
不太相关的模块可以被弃用并从主项目中移除,但仍以外部库的形式提供,例如 groovy-bsf 现在可能被认为是非必要的,因为大多数用户将拥有 jsr-223(但它可以被移到一个单独的模块中,并仍然可供任何需要它的人使用)
-
从某些功能的旧版本到新版本的受控迁移,例如,我们可以生成一个 groovy-xml-v2 库,它可能存在重大更改 - v2 库最初可能是一个可选模块,但后来会成为主要支持选项 - 旧版本的用户将能够 “指向旧版本”,以便他们的脚本不会在他们希望的情况下中断(稍后将提供更多详细信息)
-
外部模块可以更轻松地集成到核心发行版中(用户可以自定义某些方面的内容,例如捆绑的内容)
-
我们可以提供包含已弃用功能或不可预见的重大更改的“旧版本” jar 文件 - 库编写者可以将旧版本 jar 文件集成到他们的库中,以便更轻松地在多个版本的 Groovy 中支持使用他们的库
配置 Groovy 安装
Groovy 使用 conf/groovy-starter.conf 文件中的文件引导其配置。它具有如下条目
# load required libraries
load !{groovy.home}/lib/*.jar
必要的 jar 文件位于 Groovy 安装的一部分的 lib 目录中。
Groovy 安装现在可能会有一个“modules”(或组件或存储库)目录。groovy-starter.conf 文件将具有以下额外条目
# load SQL component
grab org.codehaus.groovy groovy-sql 1.9.0
# load XML component
grab org.codehaus.groovy groovy-xml 1.9.0
Grapes 通过 Ivy 加载,并从设置文件配置。此文件可能具有以下额外条目
<ibiblio name="modules" root="file:${groovy.home}/modules/" m2compatible="true"/>
Ivy 库(或者可能是 wharf 或 aether 库)可能会成为必要的 jar 文件 - 尽管可能只有非常有限形式的 grab 受支持,在这种情况下可能不需要额外的库。
运行时挂钩/注册
下载 grape 时,其 jar 文件中的类将被添加到类路径(当前追加)。此外,我们计划支持额外的集成点
潜在挂钩 | 目的 | 状态 |
---|---|---|
|
允许模块定义其他类别方法 |
现在位于 |
|
允许模块定义其他静态类别方法 |
现在位于 |
|
允许模块定义已被序列化的其他类别方法 |
延迟 |
|
允许模块定义其他 ExpandoMetaClass 方法 |
延迟 |
|
允许模块定义其他元类,类似于当前的魔术包机制 [1] |
延迟 |
|
允许模块定义其他普通导入、星号导入、静态导入、别名 |
已移至编译器配置 |
|
允许模块定义支持的文件扩展名 |
已移至编译器配置 |
|
允许模块定义 AST 转换 |
现在位于 |
? |
提供一种注册构建元数据的方法 |
延迟 |
? |
是否应该有一种方法可以 “发布” 新的命令行级启动脚本,例如 java2groovy |
延迟 |
? |
提供一种注册运行器类的方法,例如 EasyB - 也可能需要检测运行器类型 |
现在位于 |
? |
提供一种注册特殊编译器标志的方法,例如 “--indy” |
延迟 |
? |
提供一种注入特殊 AST 自定义项的方法 |
延迟 |
这也是我们可以在其中指定额外要求的地方,例如要求 “invoke dynamic” - 但也请参见稍后的内容。我们是否可以声明性地指定我们的安全策略要求?或者我们是否可以禁用功能的特定方面,例如禁用一些标准的全局 AST 转换,因为我们想提供一个更好的转换?(这显然对安全性有影响!)
另一个问题是所有这些功能是否也将在 API 中可用。这样的 API 是否允许模块被 “取消注册”?
Groovydoc/源代码指针
某些模块化系统支持与模块一起 “安装” 文档(和/或源代码)。模块是否应该包含指向其 GroovyDoc 和/或源代码的指针(或与它们捆绑在一起)。
在 Java 生态系统中,许多库按照通用约定发布其 javadoc/sources,或者在网上提供 javadoc。我们是否依赖于这些既定的约定,还是提供额外的支持?对于没有访问复杂 IDE 的用户来说,在同一个地方提供所有文档的“合并”形式会很方便。
运行时内省
在 Groovy 中,您目前可以使用以下方法确定 Groovy 版本
println GroovySystem.version
它返回一个字符串。
在 GROOVY-2422 中,它讨论了对其他版本检查的渴望。
它还讨论了列出功能。这可能是 “is invokeDynamic” 可用,或者实际上只是关于可用的已加载模块。通常情况下,我们希望我们的依赖项被指定为我们 pom 的一部分,并自动加载,但有时做一些特殊的事情会很有用。
一般来说,我们是否应该能够找到已加载模块和版本的列表?或者询问特定类属于哪个模块/版本?
构建影响
这里讨论了大部分内容:Groovy 2.0 模块化
每个 “子模块” 是否应该能够独立构建?它是否会有自己的 javadoc、自己的代码风格规则、自己的覆盖率指标等等。
模块健壮性
我们是否应该提供一个标准的挂钩/机制来尝试解决以下场景
-
您正在加载依赖于根类加载器管理的类的 jar 文件?
-
在您的类之前,类路径上已经存在同名类?
-
类路径上已经存在与您的依赖项之一同名但来自不兼容版本的类
-
能够注册一个 “ping”/健康检查方法,以便快速测试组件
协助 IDE 支持
我们可以定义一个标准位置或约定,例如 META-INF/services/groovy/dsld 或 META-INF/services/groovy/gdsl,IDEs 可以在其中找到与该模块相关的 DSL 描述符。
日志记录
模块本身是否应该有一种标准的日志记录方法?是 j.u.l.Logger 吗?也许与 slf4j 桥接?
参考资料和有用链接
维基页面(网络档案)
更新历史
- 4 (2011-10-26)
-
从 Codehaus 维基中提取的版本
- 5 (2018-10-24)
-
许多细微调整