動態語言支援

Spring 提供了全面的支援,可將使用動態語言 (例如 Groovy) 定義的類別和物件與 Spring 搭配使用。此支援讓您可以使用支援的動態語言撰寫任意數量的類別,並讓 Spring 容器透明地實例化、組態和相依性注入產生的物件。

Spring 的腳本支援主要針對 Groovy 和 BeanShell。除了這些特別支援的語言之外,JSR-223 腳本機制也支援與任何具備 JSR-223 功能的語言供應商整合(截至 Spring 4.2),例如 JRuby。

您可以在情境中找到動態語言支援可以立即發揮作用的完整範例。

第一個範例

本章的大部分內容都在詳細描述動態語言支援。在深入探討動態語言支援的所有細節之前,我們先來看一個以動態語言定義的 Bean 的快速範例。此第一個 Bean 的動態語言是 Groovy。(此範例的基礎取自 Spring 測試套件。如果您想查看任何其他支援語言的對等範例,請查看原始碼)。

下一個範例顯示了 Messenger 介面,Groovy Bean 將實作此介面。請注意,此介面是以純 Java 定義的。注入 Messenger 參考的相依物件不知道底層實作是 Groovy 腳本。以下清單顯示了 Messenger 介面

package org.springframework.scripting;

public interface Messenger {

	String getMessage();
}

以下範例定義了一個類別,該類別具有對 Messenger 介面的相依性

package org.springframework.scripting;

public class DefaultBookingService implements BookingService {

	private Messenger messenger;

	public void setMessenger(Messenger messenger) {
		this.messenger = messenger;
	}

	public void processBooking() {
		// use the injected Messenger object...
	}
}

以下範例在 Groovy 中實作了 Messenger 介面

package org.springframework.scripting.groovy

// Import the Messenger interface (written in Java) that is to be implemented
import org.springframework.scripting.Messenger

// Define the implementation in Groovy in file 'Messenger.groovy'
class GroovyMessenger implements Messenger {

	String message
}

若要使用自訂動態語言標籤來定義動態語言支援的 Bean,您需要在 Spring XML 組態檔的頂端具有 XML Schema 前言。您也需要使用 Spring ApplicationContext 實作作為您的 IoC 容器。支援將動態語言支援的 Bean 與純 BeanFactory 實作搭配使用,但您必須管理 Spring 內部元件的細節才能做到這一點。

如需基於 Schema 的組態的詳細資訊,請參閱基於 XML Schema 的組態

最後,以下範例顯示了 Bean 定義,這些定義會影響將 Groovy 定義的 Messenger 實作注入到 DefaultBookingService 類別的實例中

<?xml version="1.0" encoding="UTF-8"?>
<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">

	<!-- this is the bean definition for the Groovy-backed Messenger implementation -->
	<lang:groovy id="messenger" script-source="classpath:Messenger.groovy">
		<lang:property name="message" value="I Can Do The Frug" />
	</lang:groovy>

	<!-- an otherwise normal bean that will be injected by the Groovy-backed Messenger -->
	<bean id="bookingService" class="x.y.DefaultBookingService">
		<property name="messenger" ref="messenger" />
	</bean>

</beans>

bookingService Bean (DefaultBookingService) 現在可以正常使用其私有 messenger 成員變數,因為注入到其中的 Messenger 實例是 Messenger 實例。這裡沒有發生任何特殊情況,只是純 Java 和純 Groovy。

希望前面的 XML 片段是不言自明的,但如果不是,也不必過於擔心。繼續閱讀以深入瞭解前面組態的緣由。

定義由動態語言支援的 Bean

本節說明如何使用任何支援的動態語言精確地定義 Spring 管理的 Bean。

請注意,本章不嘗試解釋支援的動態語言的語法和慣用語。例如,如果您想使用 Groovy 撰寫應用程式中的某些類別,我們假設您已經瞭解 Groovy。如果您需要關於動態語言本身的更多詳細資訊,請參閱本章末尾的更多資源

通用概念

使用動態語言支援的 Bean 所涉及的步驟如下

  1. 撰寫動態語言原始碼的測試 (自然地)。

  2. 然後撰寫動態語言原始碼本身。

  3. 透過在 XML 組態中使用適當的 <lang:language/> 元素來定義動態語言支援的 Bean (您可以使用 Spring API 以程式化方式定義此類 Bean,雖然您必須查閱原始碼以取得關於如何執行此操作的指示,因為本章未涵蓋此類進階組態)。請注意,這是一個迭代步驟。每個動態語言原始碼檔案至少需要一個 Bean 定義 (雖然多個 Bean 定義可以參考同一個原始碼檔案)。

前兩個步驟 (測試和撰寫您的動態語言原始碼檔案) 超出了本章的範圍。請參閱您選擇的動態語言的語言規格和參考手冊,並開始開發您的動態語言原始碼檔案。但是,您首先要閱讀本章的其餘部分,因為 Spring 的動態語言支援確實對您的動態語言原始碼檔案的內容做出了一些 (小的) 假設。

<lang:language/> 元素

前一節中清單中的最後一個步驟涉及定義動態語言支援的 Bean 定義,每個您想要組態的 Bean 各一個 (這與正常的 JavaBean 組態沒有什麼不同)。但是,您可以使用 <lang:language/> 元素來定義動態語言支援的 Bean,而不是指定要由容器實例化和組態的類別的完整限定類別名稱。

每個支援的語言都有對應的 <lang:language/> 元素

  • <lang:groovy/> (Groovy)

  • <lang:bsh/> (BeanShell)

  • <lang:std/> (JSR-223,例如,使用 JRuby)

可用於組態的確切屬性和子元素取決於 Bean 是以哪種語言定義的 (本章稍後的語言特定章節會詳細說明這一點)。

可重新整理的 Bean

Spring 中動態語言支援最引人注目的附加價值之一 (或許也是唯一一個) 是「可重新整理的 Bean」功能。

可重新整理的 Bean 是一個動態語言支援的 Bean。透過少量的組態,動態語言支援的 Bean 可以監控其底層原始碼檔案資源中的變更,然後在動態語言原始碼檔案變更時重新載入自身 (例如,當您編輯並儲存對檔案系統上的檔案的變更時)。

這讓您可以部署任意數量的動態語言原始碼檔案作為應用程式的一部分,組態 Spring 容器以建立由動態語言原始碼檔案支援的 Bean (使用本章中描述的機制),以及 (稍後,隨著需求的變更或某些其他外部因素的介入) 編輯動態語言原始碼檔案,並讓他們所做的任何變更反映在由變更的動態語言原始碼檔案支援的 Bean 中。無需關閉執行中的應用程式 (或在 Web 應用程式的情況下重新部署)。經過修改的動態語言支援的 Bean 會從變更的動態語言原始碼檔案中取得新的狀態和邏輯。

此功能預設為關閉。

現在我們可以來看一個範例,瞭解開始使用可重新整理的 Bean 有多麼容易。若要開啟可重新整理的 Bean 功能,您必須在 Bean 定義的 <lang:language/> 元素上指定正好一個額外屬性。因此,如果我們堅持使用本章稍早的範例,則以下範例顯示了我們將在 Spring XML 組態中變更什麼以影響可重新整理的 Bean

<beans>

	<!-- this bean is now 'refreshable' due to the presence of the 'refresh-check-delay' attribute -->
	<lang:groovy id="messenger"
			refresh-check-delay="5000" <!-- switches refreshing on with 5 seconds between checks -->
			script-source="classpath:Messenger.groovy">
		<lang:property name="message" value="I Can Do The Frug" />
	</lang:groovy>

	<bean id="bookingService" class="x.y.DefaultBookingService">
		<property name="messenger" ref="messenger" />
	</bean>

</beans>

這真的是您必須做的全部。在 messenger Bean 定義上定義的 refresh-check-delay 屬性是以毫秒為單位的數字,在此之後,Bean 會使用對基礎動態語言原始碼檔案所做的任何變更來重新整理。您可以透過為 refresh-check-delay 屬性指派負值來關閉重新整理行為。請記住,預設情況下,重新整理行為是停用的。如果您不想要重新整理行為,請不要定義該屬性。

如果我們然後執行以下應用程式,我們可以練習可重新整理的功能。(請原諒下一個程式碼片段中「跳過障礙暫停執行」的詭計。) System.in.read() 呼叫僅在那裡,以便程式的執行暫停,而您 (此情境中的開發人員) 離開並編輯基礎動態語言原始碼檔案,以便在程式恢復執行時,重新整理觸發動態語言支援的 Bean。

以下清單顯示了此範例應用程式

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scripting.Messenger;

public final class Boot {

	public static void main(final String[] args) throws Exception {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
		Messenger messenger = (Messenger) ctx.getBean("messenger");
		System.out.println(messenger.getMessage());
		// pause execution while I go off and make changes to the source file...
		System.in.read();
		System.out.println(messenger.getMessage());
	}
}

然後假設,為了此範例的目的,對 Messenger 實作的 getMessage() 方法的所有呼叫都必須變更,以便訊息以引號括住。以下清單顯示了當程式執行暫停時,您 (開發人員) 應該對 Messenger.groovy 原始碼檔案進行的變更

package org.springframework.scripting

class GroovyMessenger implements Messenger {

	private String message = "Bingo"

	public String getMessage() {
		// change the implementation to surround the message in quotes
		return "'" + this.message + "'"
	}

	public void setMessage(String message) {
		this.message = message
	}
}

當程式執行時,輸入暫停之前的輸出將為 I Can Do The Frug。在對原始碼檔案進行變更並儲存且程式恢復執行後,在動態語言支援的 Messenger 實作上呼叫 getMessage() 方法的結果為 'I Can Do The Frug' (請注意包含額外的引號)。

如果腳本的變更發生在 refresh-check-delay 值的視窗內,則對腳本的變更不會觸發重新整理。實際上,在動態語言支援的 Bean 上呼叫方法之前,不會擷取對腳本的變更。只有在動態語言支援的 Bean 上呼叫方法時,它才會檢查其基礎腳本來源是否已變更。任何與重新整理腳本相關的例外狀況 (例如遇到編譯錯誤或發現腳本檔案已刪除) 都會導致致命例外狀況傳播到呼叫程式碼。

先前描述的可重新整理的 Bean 行為不適用於使用 <lang:inline-script/> 元素標記法定義的動態語言原始碼檔案 (請參閱內聯動態語言原始碼檔案)。此外,它僅適用於可以實際偵測到基礎原始碼檔案變更的 Bean (例如,透過檢查檔案系統上存在的動態語言原始碼檔案的上次修改日期的程式碼)。

內聯動態語言原始碼檔案

動態語言支援也可以滿足直接嵌入在 Spring Bean 定義中的動態語言原始碼檔案。更具體來說,<lang:inline-script/> 元素可讓您在 Spring 組態檔中立即定義動態語言來源。範例可能會闡明內聯腳本功能的工作方式

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

		package org.springframework.scripting.groovy

		import org.springframework.scripting.Messenger

		class GroovyMessenger implements Messenger {
			String message
		}

	</lang:inline-script>
	<lang:property name="message" value="I Can Do The Frug" />
</lang:groovy>

如果我們將定義 Spring 組態檔內部的動態語言來源是否為良好實務的問題放在一邊,則 <lang:inline-script/> 元素在某些情況下可能很有用。例如,我們可能想要快速將 Spring Validator 實作新增至 Spring MVC Controller。這只是使用內聯來源的一下子工作。(請參閱腳本化驗證器以取得此類範例。)

瞭解動態語言支援的 Bean 環境中的建構子注入

關於 Spring 的動態語言支援,有一件非常重要的事情需要注意。也就是說,您不能 (目前) 為動態語言支援的 Bean 提供建構子引數 (因此,建構子注入不適用於動態語言支援的 Bean)。為了使這種對建構子和屬性的特殊處理 100% 清晰,以下程式碼和組態的混合不起作用

一種無法運作的方法
package org.springframework.scripting.groovy

import org.springframework.scripting.Messenger

// from the file 'Messenger.groovy'
class GroovyMessenger implements Messenger {

	GroovyMessenger() {}

	// this constructor is not available for Constructor Injection
	GroovyMessenger(String message) {
		this.message = message;
	}

	String message

	String anotherMessage
}
<lang:groovy id="badMessenger"
	script-source="classpath:Messenger.groovy">
	<!-- this next constructor argument will not be injected into the GroovyMessenger -->
	<!-- in fact, this isn't even allowed according to the schema -->
	<constructor-arg value="This will not work" />

	<!-- only property values are injected into the dynamic-language-backed object -->
	<lang:property name="anotherMessage" value="Passed straight through to the dynamic-language-backed object" />

</lang>

實際上,此限制並不像最初看起來那麼重要,因為 setter 注入是絕大多數開發人員偏好的注入樣式 (我們將關於這是否是一件好事的討論留到以後再說)。

Groovy Bean

本節說明如何在 Spring 中使用 Groovy 中定義的 Bean。

Groovy 首頁包含以下描述

「Groovy 是一種適用於 Java 2 平台的敏捷動態語言,它具有許多人在 Python、Ruby 和 Smalltalk 等語言中非常喜歡的功能,讓 Java 開發人員可以使用類似 Java 的語法。」

如果您從頭到尾閱讀本章,您已經看過一個範例,其中包含一個 Groovy 動態語言支援的 Bean。現在考慮另一個範例 (再次使用 Spring 測試套件中的範例)

package org.springframework.scripting;

public interface Calculator {

	int add(int x, int y);
}

以下範例在 Groovy 中實作了 Calculator 介面

package org.springframework.scripting.groovy

// from the file 'calculator.groovy'
class GroovyCalculator implements Calculator {

	int add(int x, int y) {
		x + y
	}
}

以下 Bean 定義使用了在 Groovy 中定義的計算器

<!-- from the file 'beans.xml' -->
<beans>
	<lang:groovy id="calculator" script-source="classpath:calculator.groovy"/>
</beans>

最後,以下小型應用程式練習了前面的組態

package org.springframework.scripting;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
		Calculator calc = ctx.getBean("calculator", Calculator.class);
		System.out.println(calc.add(2, 8));
	}
}

執行上述程式所產生的輸出結果(毫不意外地)是 10。(如需更多有趣的範例,請參閱動態語言展示專案以取得更複雜的範例,或參閱本章稍後的 情境 範例)。

您不得在每個 Groovy 原始碼檔案中定義一個以上的類別。雖然這在 Groovy 中是完全合法的,但(可以說)這是一個不好的實務。為了方法一致性,您應該(根據 Spring 團隊的意見)尊重每個原始碼檔案一個(public)類別的標準 Java 慣例。

使用回呼自訂 Groovy 物件

GroovyObjectCustomizer 介面是一個回呼,可讓您將額外的建立邏輯掛鉤到建立 Groovy 支援的 bean 的過程中。例如,此介面的實作可以調用任何需要的初始化方法、設定一些預設屬性值,或指定自訂的 MetaClass。以下列表顯示了 GroovyObjectCustomizer 介面定義

public interface GroovyObjectCustomizer {

	void customize(GroovyObject goo);
}

Spring Framework 會實例化您的 Groovy 支援的 bean 的實例,然後將建立的 GroovyObject 傳遞給指定的 GroovyObjectCustomizer(如果已定義)。您可以對提供的 GroovyObject 參考執行任何操作。我們預期大多數人希望使用此回呼設定自訂的 MetaClass,以下範例示範了如何執行此操作

public final class SimpleMethodTracingCustomizer implements GroovyObjectCustomizer {

	public void customize(GroovyObject goo) {
		DelegatingMetaClass metaClass = new DelegatingMetaClass(goo.getMetaClass()) {

			public Object invokeMethod(Object object, String methodName, Object[] arguments) {
				System.out.println("Invoking '" + methodName + "'.");
				return super.invokeMethod(object, methodName, arguments);
			}
		};
		metaClass.initialize();
		goo.setMetaClass(metaClass);
	}

}

完整討論 Groovy 中的元編程已超出 Spring 參考手冊的範圍。請參閱 Groovy 參考手冊的相關章節或在線上搜尋。有大量文章討論此主題。實際上,如果您使用 Spring 命名空間支援,則使用 GroovyObjectCustomizer 很簡單,如下列範例所示

<!-- define the GroovyObjectCustomizer just like any other bean -->
<bean id="tracingCustomizer" class="example.SimpleMethodTracingCustomizer"/>

	<!-- ... and plug it into the desired Groovy bean via the 'customizer-ref' attribute -->
	<lang:groovy id="calculator"
		script-source="classpath:org/springframework/scripting/groovy/Calculator.groovy"
		customizer-ref="tracingCustomizer"/>

如果您不使用 Spring 命名空間支援,您仍然可以使用 GroovyObjectCustomizer 功能,如下列範例所示

<bean id="calculator" class="org.springframework.scripting.groovy.GroovyScriptFactory">
	<constructor-arg value="classpath:org/springframework/scripting/groovy/Calculator.groovy"/>
	<!-- define the GroovyObjectCustomizer (as an inner bean) -->
	<constructor-arg>
		<bean id="tracingCustomizer" class="example.SimpleMethodTracingCustomizer"/>
	</constructor-arg>
</bean>

<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
您也可以在與 Spring 的 GroovyObjectCustomizer 相同的位置指定 Groovy CompilationCustomizer(例如 ImportCustomizer)甚至完整的 Groovy CompilerConfiguration 物件。此外,您可以在 ConfigurableApplicationContext.setClassLoader 層級為您的 bean 設定具有自訂組態的通用 GroovyClassLoader;這也會導致共用 GroovyClassLoader 的使用,因此在大量腳本化 bean 的情況下建議使用(避免每個 bean 都有隔離的 GroovyClassLoader 實例)。

BeanShell Bean

本節說明如何在 Spring 中使用 BeanShell bean。

BeanShell 首頁 包含以下描述

BeanShell is a small, free, embeddable Java source interpreter with dynamic language
features, written in Java. BeanShell dynamically runs standard Java syntax and
extends it with common scripting conveniences such as loose types, commands, and method
closures like those in Perl and JavaScript.

與 Groovy 相反,BeanShell 支援的 bean 定義需要一些(小的)額外組態。Spring 中 BeanShell 動態語言支援的實作很有趣,因為 Spring 會建立一個 JDK 動態代理,該代理實作在 <lang:bsh> 元素的 script-interfaces 屬性值中指定的所有介面(這就是為什麼您必須在屬性值中至少提供一個介面,因此,當您使用 BeanShell 支援的 bean 時,請針對介面編程)。這表示對 BeanShell 支援的物件的每個方法調用都會通過 JDK 動態代理調用機制。

現在我們可以展示一個完整可運作的範例,該範例使用實作 Messenger 介面的基於 BeanShell 的 bean,該介面在本章稍早定義。我們再次展示 Messenger 介面的定義

package org.springframework.scripting;

public interface Messenger {

	String getMessage();
}

以下範例顯示 BeanShell “實作”(這裡我們鬆散地使用這個詞)Messenger 介面

String message;

String getMessage() {
	return message;
}

void setMessage(String aMessage) {
	message = aMessage;
}

以下範例顯示定義上述“類別”的“實例”的 Spring XML(同樣,我們在這裡非常鬆散地使用這些術語)

<lang:bsh id="messageService" script-source="classpath:BshMessenger.bsh"
	script-interfaces="org.springframework.scripting.Messenger">

	<lang:property name="message" value="Hello World!" />
</lang:bsh>

有關您可能想要使用基於 BeanShell 的 bean 的一些情境,請參閱 情境

情境

在腳本語言中定義 Spring 管理的 bean 可能有益的可能情境非常多樣。本節描述了 Spring 中動態語言支援的兩種可能用例。

腳本化的 Spring MVC 控制器

可以從使用動態語言支援的 bean 中受益的一組類別是 Spring MVC 控制器。在純 Spring MVC 應用程式中,透過 Web 應用程式的導航流程在很大程度上取決於封裝在 Spring MVC 控制器中的程式碼。由於 Web 應用程式的導航流程和其他呈現層邏輯需要更新以響應支援問題或不斷變化的業務需求,因此可能更容易透過編輯一個或多個動態語言原始碼檔案來實現任何此類需要的變更,並看到這些變更立即反映在正在運行的應用程式的狀態中。

請記住,在 Spring 等專案所提倡的輕量級架構模型中,您的目標通常是擁有一個非常薄的呈現層,應用程式的所有重要業務邏輯都包含在網域和服務層類別中。將 Spring MVC 控制器開發為動態語言支援的 bean 可讓您透過編輯和儲存文字檔案來變更呈現層邏輯。對此類動態語言原始碼檔案的任何變更(取決於組態)都會自動反映在由動態語言原始碼檔案支援的 bean 中。

為了實現對動態語言支援的 bean 的任何變更的自動“拾取”,您必須啟用“可重新整理的 bean”功能。有關此功能的完整處理,請參閱 可重新整理的 Bean

以下範例顯示使用 Groovy 動態語言實作的 org.springframework.web.servlet.mvc.Controller

package org.springframework.showcase.fortune.web

import org.springframework.showcase.fortune.service.FortuneService
import org.springframework.showcase.fortune.domain.Fortune
import org.springframework.web.servlet.ModelAndView
import org.springframework.web.servlet.mvc.Controller

import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse

// from the file '/WEB-INF/groovy/FortuneController.groovy'
class FortuneController implements Controller {

	@Property FortuneService fortuneService

	ModelAndView handleRequest(HttpServletRequest request,
			HttpServletResponse httpServletResponse) {
		return new ModelAndView("tell", "fortune", this.fortuneService.tellFortune())
	}
}
<lang:groovy id="fortune"
		refresh-check-delay="3000"
		script-source="/WEB-INF/groovy/FortuneController.groovy">
	<lang:property name="fortuneService" ref="fortuneService"/>
</lang:groovy>

腳本化的驗證器

應用程式開發中使用 Spring 的另一個領域,可能會受益於動態語言支援的 bean 所提供的彈性,那就是驗證。與常規 Java 相比,使用鬆散類型的動態語言(也可能支援內聯正則表達式)來表達複雜的驗證邏輯可能更容易。

同樣,將驗證器開發為動態語言支援的 bean 可讓您透過編輯和儲存簡單的文字檔案來變更驗證邏輯。任何此類變更(取決於組態)都會自動反映在正在運行的應用程式的執行中,而無需重新啟動應用程式。

為了實現對動態語言支援的 bean 的任何變更的自動“拾取”,您必須啟用“可重新整理的 bean”功能。有關此功能的完整詳細處理,請參閱 可重新整理的 Bean

以下範例顯示使用 Groovy 動態語言實作的 Spring org.springframework.validation.Validator(有關 Validator 介面的討論,請參閱 使用 Spring 的 Validator 介面進行驗證

import org.springframework.validation.Validator
import org.springframework.validation.Errors
import org.springframework.beans.TestBean

class TestBeanValidator implements Validator {

	boolean supports(Class clazz) {
		return TestBean.class.isAssignableFrom(clazz)
	}

	void validate(Object bean, Errors errors) {
		if(bean.name?.trim()?.size() > 0) {
			return
		}
		errors.reject("whitespace", "Cannot be composed wholly of whitespace.")
	}
}

其他詳細資訊

最後一節包含一些與動態語言支援相關的其他詳細資訊。

AOP — 建議腳本化的 Bean

您可以使用 Spring AOP 框架來建議腳本化的 bean。Spring AOP 框架實際上並不知道正在建議的 bean 可能是腳本化的 bean,因此您使用(或旨在使用)的所有 AOP 用例和功能都適用於腳本化的 bean。當您建議腳本化的 bean 時,您不能使用基於類別的代理。您必須使用 基於介面的代理

您不僅限於建議腳本化的 bean。您也可以使用支援的動態語言編寫切面本身,並使用此類 bean 來建議其他 Spring bean。雖然這確實是對動態語言支援的進階使用。

作用域

如果這不是顯而易見的,則腳本化的 bean 可以像任何其他 bean 一樣設定作用域。各種 <lang:language/> 元素上的 scope 屬性可讓您控制底層腳本化 bean 的作用域,就像對常規 bean 一樣。(預設作用域是 singleton,就像“常規” bean 一樣。)

以下範例使用 scope 屬性定義一個作用域設定為 prototype 的 Groovy bean

<?xml version="1.0" encoding="UTF-8"?>
<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="messenger" script-source="classpath:Messenger.groovy" scope="prototype">
		<lang:property name="message" value="I Can Do The RoboCop" />
	</lang:groovy>

	<bean id="bookingService" class="x.y.DefaultBookingService">
		<property name="messenger" ref="messenger" />
	</bean>

</beans>

有關 Spring Framework 中作用域支援的完整討論,請參閱 Bean 作用域,位於 IoC 容器 中。

lang XML 結構描述

Spring XML 組態中的 lang 元素用於處理公開以動態語言(例如 Groovy 或 BeanShell)編寫的物件作為 Spring 容器中的 bean。

這些元素(和動態語言支援)在 動態語言支援 中得到了全面涵蓋。有關此支援和 lang 元素的完整詳細資訊,請參閱該章節。

若要使用 lang 結構描述中的元素,您需要在 Spring XML 組態檔案的頂部加入以下前言。以下程式碼片段中的文字參考了正確的結構描述,以便 lang 命名空間中的標籤可供您使用

<?xml version="1.0" encoding="UTF-8"?>
<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">

	<!-- bean definitions here -->

</beans>

更多資源

以下連結指向有關本章中引用的各種動態語言的更多資源