知識庫 / Groovy RSS 訂閱

Groovy 在 Spring 中的應用

Groovy,Spring
HongKong
10
11:51 AM · Dec 06 ,2025

1. 概述

Groovy 是一種功能強大且動態的 JVM 語言,具有眾多特性。使用 Groovy 與 Spring 結合可以極大地增強應用程序的靈活性和可讀性。Spring 從版本 4 開始支持基於 Groovy 的配置。

在本教程中,我們將探討如何使用 Groovy 與 Spring 結合使用。首先,我們將學習如何使用 Spring 提供的多種選項創建 Groovy bean 定義。接下來,我們將討論如何使用 Groovy 腳本啓動 Application Context。最後,我們將學習如何使用 XML 和 GroovyScriptEngine 類執行 Groovy 腳本(無需編譯)。

2. Maven 依賴

讓我們首先在 <em>pom.xml</em> 中定義 Groovy 依賴:

<dependency>
    <groupId>org.apache.groovy</groupId>
    <artifactId>groovy</artifactId>
    <version>4.0.21</version>
</dependency>

此外,還需要添加 GMavenPlus 插件來編譯 Groovy 文件:

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.gmavenplus</groupId>
            <artifactId>gmavenplus-plugin</artifactId>
            <version>3.0.2</version>
            <executions>
                <execution>
                    <goals>
                        <goal>addSources</goal>
                        <goal>addTestSources</goal>
                        <goal>generateStubs</goal>
                        <goal>compile</goal>
                        <goal>generateTestStubs</goal>
                        <goal>compileTests</goal>
                        <goal>removeStubs</goal>
                        <goal>removeTestStubs</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

3. Bean 定義

傳統上,開發者使用 XML 配置來聲明 Bean。這種風格後來被定義 Bean 的程序方式,即通過 Java 註解。 另一種聲明 Bean 的方式是通過 Groovy 腳本。

由於我們使用 GMavenPlus 插件,Groovy 源代碼可以與 Java 代碼混合存在於 src/main/java 源代碼文件夾中。 但是,為了避免將來混淆,最好將 Groovy 文件放在專門的 src/main/groovy 源代碼文件夾中

3.1. 使用 Groovy Bean Builder

Groovy Bean Builder 是一個強大的替代方案,可以替代 Java 中基於 @Configuration 註解以及基於 XML 的配置方式。下面我們通過 Groovy 代碼來查看一些基本的 Bean 定義:

beans {
    
    // Declares a simple bean with a constructor argument
    company(Company, name: 'ABC Inc');

    // The same bean can be declared using a simpler syntax: beanName(type, constructor-args) 
    company String, 'ABC Inc'

    // Declares an employee object with setters referencing the previous bean
    employee(Employee) {
        firstName = 'Lakshmi'
        lastName = 'Priya'
        // References to other beans can be done in both the ways
        vendor = company // or vendor = ref('company')
    }
    // Allows import of other configuration files, both XML and Groovy
    importBeans('classpath:ApplicationContext.xml')
    importBeans('classpath:GroovyContext.groovy')
}

在這裏,頂層 <em >beans</em > 構造,它包圍了所有聲明的 beans,是一個閉包,<a href="https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/groovy/GroovyBeanDefinitionReader.html"><em >GroovyBeanDefinitionReader</em ></a> 作為一個 DSL 進行處理。

3.2. 使用註釋

或者,Groovy 類可以作為有效的 Spring Bean,並且 Groovy 可以用作 Java 的替代品,用於基於註釋的配置:

@Configuration
class SpringGroovyConfiguration{
    
    @Bean
    List<String> fruits() {
        ['Apple', 'Orange', 'Banana', 'Grapes']
    }

    @Bean
    Map<Integer, String> rankings() {
        [1: 'Gold', 2: 'Silver', 3: 'Bronze']
    }
}

3.3. 使用 XML

當然,Groovy Bean Builder 和基於註解的配置都更具靈活性。但是,我們仍然可以使用 XML 來聲明在 Groovy 腳本中定義的 Bean。Groovy 是一種 動態語言,Spring 提供了全面的支持。因此,我們需要在 XML 配置中使用一個特殊元素 (<lang:groovy>) 來指示我們正在定義具有動態語言支持的 Bean

例如,讓我們來看一個引用正確模式的 XML 配置,以便在 lang 命名空間中的標籤可用:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/lang https://www.springframework.org/schema/lang/spring-lang.xsd">
    <lang:groovy id="notification" script-source="file:NotificationServiceImpl.groovy" refresh-check-delay="10000" >
        <lang:property name="message" value="Hello" />
    </lang:groovy>
</beans>

在這裏,我們聲明瞭notification Bean,該 Bean 通過script-source 屬性引用了一個 Groovy 腳本。我們可以使用file 前綴指定腳本的精確位置。 另一種方法是使用classpath 前綴直接從 classpath 訪問資源。 refresh-check-delay 屬性定義了腳本的刷新間隔,當腳本內容發生更改時,腳本可以自動刷新。

4. Bootstrap 應用上下文

Spring 需要知道如何啓動 Groovy 上下文文件,以便將 Bean 使其可用於應用程序。我們可以通過在 web.xml 中進行配置,或者通過程序方式加載上下文來實現。

4.1. 在 web.xml 中添加 Groovy 配置

為了簡化操作,Spring 4.1 通過使用 GroovyWebApplicationContext,支持在 web.xml 中加載 Groovy 配置文件。

默認情況下,配置將從 /WEB-INF/applicationContext.groovy 加載。但是,可以通過 contextConfigLocation servlet 上下文參數進行覆蓋:

<web-app>
    
    ...
    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.GroovyWebApplicationContext</param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/applicationContext.groovy</param-value>
    </context-param>
    
    ...
</web-app>

4.2. 使用 `GenericGroovyApplicationContext

Spring 提供 `GenericGroovyApplicationContext 用於啓動 Groovy Bean 定義。 此外,上下文還可以通過內聯 Bean 定義閉包加載:

def context = new GenericGroovyApplicationContext()
context.reader.beans {
    department(Department) {
        name = 'Finance'
        floor = 3
    }
}
context.refresh()

或者,我們也可以外部化這個 Bean 定義,並從 Groovy 配置文件中加載應用程序上下文:

GenericGroovyApplicationContext context = new GenericGroovyApplicationContext();
context.load("config/applicationContext.groovy");
context.refresh();

如我們所見,加載 Groovy 上下文與 Java 風格的 XmlWebApplicationContextClassPathXmlApplicationContext 實例化方式類似。

在沒有額外配置的情況下,代碼可以更簡潔:

ApplicationContext context = new GenericGroovyApplicationContext("config/applicationContext.groovy");
String foo = context.getBean("foo", String.class);

此外,GenericGroovyApplicationContext  也能夠理解 XML Bean 定義文件。 這增加了靈活性,允許與 Groovy Bean 定義文件無縫混合和匹配。

5. 執行 Groovy 腳本

除了 Groovy Bean 定義之外,Spring 還支持執行 Groovy 腳本,無需編譯。這種執行方式可以作為獨立的 Bean 執行,也可以通過在 Bean 中調用 Groovy 腳本,使腳本成為其可執行的一部分。

5.1. 作為內聯腳本

正如我們之前所見,我們可以利用 Spring 提供的動態語言支持,將 Groovy 源代碼直接嵌入到 Spring bean 定義中。因此,我們可以使用 <lang:inline-script/> 元素在 Spring 配置 XML 文件中立即定義 Groovy 源代碼。

例如,我們可以使用內聯腳本功能創建一個 Notifier bean:

<lang:groovy id="notifier">
    <lang:inline-script>

    package com.baeldung.springgroovyconfig;
    import com.baeldung.springgroovyconfig.NotificationService;

    class Notifier implements NotificationService {
        String message
    }

    </lang:inline-script>
    <lang:property name="message" value="Have a nice day!" />
</lang:groovy>

5.2. 使用 GroovyScriptEngine

或者,我們可以使用 GroovyScriptEngine 類來執行 Groovy 腳本。 GroovyScriptEngine 是由 Groovy 本身提供的,使用它不需要依賴 Spring。

這個類 支持在腳本發生更改時自動重新加載腳本。 此外,它還會加載所有依賴於它的類。

執行腳本有兩方式。 在第一種方式中,我們獲取一個 GroovyObject 並通過調用 invokeMethod() 執行腳本:

GroovyScriptEngine engine = new GroovyScriptEngine(ResourceUtils.getFile("file:src/main/resources/")
.getAbsolutePath(), this.getClass().getClassLoader());
Class<GroovyObject> joinerClass = engine.loadScriptByName("StringJoiner.groovy");
GroovyObject joiner = joinerClass.newInstance();

Object result = joiner.invokeMethod("join", new Object[]{"Mr.", "Bob"});
assertEquals("Mr.Bob", result.toString());

在第二種方法中,我們可以直接調用 Groovy 腳本。我們使用 Binding 類將變量傳遞給 Groovy 腳本:

Binding binding = new Binding();
binding.setVariable("arg1", "Mr.");
binding.setVariable("arg2", "Bob");
Object result = engine.run("StringJoinerScript.groovy", binding); 
assertEquals("Mr.Bob", result.toString());

6. 結論

Spring 提供了大量的選項來集成 Groovy。 憑藉腳本能力,使用像 Groovy 這樣動態語言在 Spring 應用中具有強大的優勢。 Spring 的適應性與 Groovy 的靈活性相結合,創造出一種絕佳的組合。

在本文中,我們學習了 Spring 框架如何提供廣泛的支持,以便我們可以使用不同的方法使用有效 Bean 定義。 此外,我們還看到了如何將 Groovy 腳本引導到有效的 Spring Bean 中。 最後,我們討論瞭如何隨時調用 Groovy 腳本。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.