GEP-9


元数据
编号

GEP-9

标题

模块化

版本

5

类型

功能

状态

最终

评论

已整合到 Groovy 2.0 中的部分

负责人

Paul King

创建

2011-10-26

最后修改 

2018-10-24

摘要:模块化

此 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 文件中的类将被添加到类路径(当前追加)。此外,我们计划支持额外的集成点

潜在挂钩 目的 状态

META-INF/services/
org.codehaus.groovy.runtime.CategoryMethods

允许模块定义其他类别方法

现在位于 META-INF/groovy/
org.codehaus.groovy.runtime.ExtensionModuleSpec

META-INF/services/
org.codehaus.groovy.runtime.StaticCategoryMethods

允许模块定义其他静态类别方法

现在位于 META-INF/groovy/
org.codehaus.groovy.runtime.ExtensionModuleSpec

META-INF/services/
org.codehaus.groovy.runtime.SerializedCategoryMethods

允许模块定义已被序列化的其他类别方法

延迟

META-INF/services/
org.codehaus.groovy.runtime.ExpandoMethods

允许模块定义其他 ExpandoMetaClass 方法

延迟

META-INF/services/
org.codehaus.groovy.runtime.DefaultMetaClasses

允许模块定义其他元类,类似于当前的魔术包机制 [1]

延迟

META-INF/services/groovy/defaultImports

允许模块定义其他普通导入、星号导入、静态导入、别名

已移至编译器配置

META-INF/services/groovy/defaultExtensions

允许模块定义支持的文件扩展名

已移至编译器配置

META-INF/services/groovy/defaultAstTransforms

允许模块定义 AST 转换

现在位于 META-INF/services/
org.codehaus.groovy.transform.ASTTransformation

?

提供一种注册构建元数据的方法

延迟

?

是否应该有一种方法可以 “发布” 新的命令行级启动脚本,例如 java2groovy

延迟

?

提供一种注册运行器类的方法,例如 EasyB - 也可能需要检测运行器类型

现在位于 META-INF/groovy/
org.apache.groovy.plugin.GroovyRunner

?

提供一种注册特殊编译器标志的方法,例如 “--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)

许多细微调整


1. 这需要与定义自定义元类的现有魔术包机制相协调。