Groovy Support

在 Spring Integration 2.0 中,我们添加了 Groovy 支持,以便你可以使用 Groovy 脚本语言为各种集成组件提供逻辑,类似于 Spring 表达式语言 (SpEL) 受支持用于路由、转换和其他集成问题的方式。有关 Groovy 的更多信息,请参阅 Groovy 文档,你可以在 project website 中找到它。 你需要将此依赖项包含在你的项目中:

  • Maven

  • Gradle

<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-groovy</artifactId>
    <version>{project-version}</version>
</dependency>
compile "org.springframework.integration:spring-integration-groovy:{project-version}"

此外,从 6.0 版本开始,为集成流程配置提供 Groovy DSL

Groovy Configuration

使用 Spring Integration 2.1,groovy 支持的配置命名空间是 Spring Integration 脚本支持的扩展,并且共享 Scripting Support 部分中详细描述的核心配置和行为。尽管 groovy 脚本得到了通用脚本支持的充分支持,但 groovy 支持提供了 Groovy 配置命名空间,该命名空间受 Spring Framework 的 org.springframework.scripting.groovy.GroovyScriptFactory 及相关组件的支持,为使用 groovy 提供了扩展功能。以下列表显示两个示例配置:

Filter
<int:filter input-channel="referencedScriptInput">
   <int-groovy:script location="some/path/to/groovy/file/GroovyFilterTests.groovy"/>
</int:filter>

<int:filter input-channel="inlineScriptInput">
     <int-groovy:script><![CDATA[
     return payload == 'good'
   ]]></int-groovy:script>
</int:filter>

正如前面的示例中所示,此配置看起来与通用脚本支持配置相同。唯一的区别是使用 Groovy 命名空间,这由 int-groovy 命名空间前缀表示。另请注意,<script> 标记上的 lang 属性在此命名空间中无效。

Groovy Object Customization

如果你需要自定义 Groovy 对象本身(不仅限于设置变量),可以使用 customizer 属性引用一个实现 GroovyObjectCustomizer 的 Bean。例如,如果你想通过修改 MetaClass 并注册要在脚本中可用的函数来实现特定于域的语言 (DSL),这可能很有用。以下示例展示了如何进行此操作:

<int:service-activator input-channel="groovyChannel">
    <int-groovy:script location="somewhere/SomeScript.groovy" customizer="groovyCustomizer"/>
</int:service-activator>

<beans:bean id="groovyCustomizer" class="org.something.MyGroovyObjectCustomizer"/>

设置自定义 GroovyObjectCustomizer<variable> 元素或 script-variable-generator 属性并不互斥。在定义内联脚本时也可以提供它。

Spring Integration 3.0 引入了 variables 属性,该属性与 variable 元素一起使用。此外,如果未提供名称的绑定变量,Groovy 脚本有能力将变量解析为 BeanFactory 中的 Bean。以下示例展示了如何使用变量 (entityManager):

<int-groovy:script>
    <![CDATA[
        entityManager.persist(payload)
        payload
    ]]>
</int-groovy:script>

entityManager 必须是应用程序上下文中的合适 Bean。

有关 `<variable>`元素、`variables`属性和 `script-variable-generator`属性的更多信息,请参见 Script Variable Bindings

Groovy Script Compiler Customization

`@CompileStatic`提示是最流行的 Groovy 编译器自定义选项。它可以在类级或方法级使用。有关详细信息,请参见 Groovy Reference Manual和,具体来说, @CompileStatic。若要将此功能用于短脚本(在集成场景中),我们被迫将简单的脚本更改为更类似于 Java 的代码。考虑以下 `<filter>`脚本:

headers.type == 'good'

前面的脚本将变成 Spring Integration 中的以下方法:

@groovy.transform.CompileStatic
String filter(Map headers) {
	headers.type == 'good'
}

filter(headers)

这样,filter() 方法就被转换为静态 Java 代码并编译,从而绕过了 Groovy 动态调用阶段,如 getProperty() 工厂和 CallSite 代理。

从 4.3 版开始,你可以使用 compile-static boolean 选项配置 Spring Integration Groovy 组件,该选项指定应将 @CompileStaticASTTransformationCustomizer 添加到内部 CompilerConfiguration。这样做后,你可以在我们的脚本代码中省略带 @CompileStatic 的方法声明,并且仍然可以获取已编译的纯 Java 代码。在这种情况下,前面的脚本可以很短,但仍然需要比解释脚本更详细,如下面的示例所示:

binding.variables.headers.type == 'good'

你必须通过 groovy.lang.Script binding 属性访问 headerspayload(或任何其他)变量,因为使用 @CompileStatic 时,我们没有动态 GroovyObject.getProperty() 功能。

此外,我们引入了 compiler-configuration bean 引用。有了此属性,你可以提供任何其他所需的 Groovy 编译器自定义项,例如 ImportCustomizer 。有关此功能的更多信息,请参阅 groovy 文档中的 advanced compiler configuration

使用 compilerConfiguration 不会自动为 @CompileStatic 注解添加 ASTTransformationCustomizer,并且会覆盖 compileStatic 选项。如果你仍然需要 CompileStatic,你应该手动将 new ASTTransformationCustomizer(CompileStatic.class) 添加到该自定义 compilerConfigurationCompilationCustomizers 中。

Groovy 编译器定制对 refresh-check-delay 选项没有任何影响,也可以编译可重新加载的脚本。

Control Bus

如 ( Enterprise Integration Patterns) 中所述,控制总线的理念是,你可以使用与 "`application-level`"消息传递相同的用于在框架内监视和管理组件的消息传递系统。在 Spring Integration 中,我们基于前面描述的适配器,以便你可以发送消息作为调用已公开操作的一种方式。这些操作的一个选项是 Groovy 脚本。以下示例为控制总线配置了 Groovy 脚本:

<int-groovy:control-bus input-channel="operationChannel"/>

控制总线具有可用于在应用程序上下文中调用 Bean 上的操作的输入通道。

Groovy 控制总线作为 Groovy 脚本在输入通道上运行消息。它获取消息,将主体编译为脚本,使用 GroovyObjectCustomizer 对其进行自定义,然后运行它。控制总线的 MessageProcessor 公开应用程序上下文中所有使用 @ManagedResource 注释并实现 Spring 的 Lifecycle 接口或扩展 Spring 的 CustomizableThreadCreator 基类的 Bean(例如,一些 TaskExecutorTaskScheduler 实现)。

请小心在控制总线命令脚本(尤其是在异步消息流中)中将托管 Bean 与自定义范围(例如“请求”)结合使用。如果控制总线 MessageProcessor 无法从应用程序上下文中公开 Bean,则可能最终会在执行命令脚本期间遇到 BeansException。例如,如果未建立自定义范围的上下文,则在该范围内获取 Bean 的尝试将触发 BeanCreationException

如果你需要进一步自定义 Groovy 对象,还可以通过 customizer 属性提供对实现 GroovyObjectCustomizer 的 Bean 的引用,如下面的例子所示:

<int-groovy:control-bus input-channel="input"
        output-channel="output"
        customizer="groovyCustomizer"/>

<beans:bean id="groovyCustomizer" class="org.foo.MyGroovyObjectCustomizer"/>