動的言語サポート

Spring は、Spring で動的言語(Groovy など)を使用して定義されたクラスとオブジェクトを使用するための包括的なサポートを提供します。このサポートにより、サポートされている動的言語で任意の数のクラスを記述し、Spring コンテナーに透過的にインスタンス化、構成、結果オブジェクトの依存性注入を行わせることができます。

Spring のスクリプトサポートは、主に Groovy および BeanShell を対象としています。これらの具体的にサポートされている言語以外に、JSR-223 スクリプトメカニズムは、JZR-223 対応の言語プロバイダー(Spring 4.2 以降)との統合がサポートされています。JRuby。

この動的言語サポートがシナリオですぐに役立つ場合の完全に機能する例を見つけることができます。

最初の例

この章の大部分は、動的言語サポートの詳細な説明に関係しています。動的言語サポートのすべてを詳しく説明する前に、動的言語で定義された Bean の簡単な例を見てみましょう。この最初の Bean の動的言語は Groovy です。(この例の基礎は Spring Test スイートから取得されました。サポートされている他の言語で同等の例を表示する場合は、ソースコードを参照してください)。

次の例は、Groovy Bean が実装する Messenger インターフェースを示しています。このインターフェースはプレーン 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 スキーマのプリアンブルが必要です。また、IoC コンテナーとして Spring ApplicationContext 実装を使用する必要があります。プレーンな BeanFactory 実装での動的言語を使用した Bean の使用はサポートされていますが、そのためには Spring 内部の接続機能を管理する必要があります。

スキーマベースの構成の詳細については、XML スキーマベースの構成を参照してください。

最後に、次の例は、Groovy で定義された Messenger 実装を DefaultBookingService クラスのインスタンスに注入する 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">

	<!-- 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 を定義できますが、これを行う方法についてはソースコードを参照する必要があります。この章では、この型の詳細設定については説明していません。これは反復的なステップであることに注意してください。動的言語ソースファイルごとに少なくとも 1 つの Bean 定義が必要です(ただし、複数の Bean 定義は同じソースファイルを参照できます)。

最初の 2 つのステップ(動的言語ソースファイルのテストと作成)は、この章の範囲外です。選択した動的言語の言語仕様とリファレンスマニュアルを参照し、動的言語ソースファイルの開発に着手します。ただし、Spring の動的言語サポートは動的言語ソースファイルの内容について(小さな)仮定を行うため、この章の残りの部分を最初に読みたいと思います。

<lang:language/> 要素

前のセクションのリストの最後のステップでは、構成する Bean ごとに 1 つずつ、動的言語でサポートされる Bean 定義を定義します (これは通常の JavaBean 構成と変わりません)。ただし、コンテナーによってインスタンス化および構成されるクラスの完全修飾クラス名を指定する代わりに、<lang:language/> 要素を使用して動的 Language-Backed Bean を定義できます。

サポートされている各言語には、対応する <lang:language/> 要素があります。

  • <lang:groovy/> (Groovy)

  • <lang:bsh/> (BeanShell)

  • <lang:std/> (JSR-223、例 JRuby)

構成に使用できる正確な属性と子要素は、Bean がどの言語で定義されているかによって異なります(この章で後述する言語固有のセクションで詳しく説明します)。

リフレッシュ可能な Bean

Spring の動的言語サポートの(そしておそらく単一の)最も魅力的な付加価値の 1 つは、「リフレッシュ可能な Bean」機能です。

リフレッシュ可能な Bean は、動的言語に対応した Bean です。少量の構成で、動的言語に裏付けされた Bean は、基礎となるソースファイルリソースの変更を監視し、動的言語ソースファイルが変更されると(たとえば、ファイルの変更を保存して、ファイルシステム)。

これにより、任意の数の動的言語ソースファイルをアプリケーションの一部としてデプロイし、(この章で説明するメカニズムを使用して)動的言語ソースファイルに裏付けられた Bean を作成するように Spring コンテナーを構成できます。外部要因が作用します)動的言語ソースファイルを編集し、変更があれば、変更された動的言語ソースファイルに裏付けられた Bean に反映されます。実行中のアプリケーションをシャットダウン(または Web アプリケーションの場合は再デプロイ)する必要はありません。このように修正された動的言語支援 Bean は、変更された動的言語ソースファイルから新しい状態とロジックを選択します。

この機能はデフォルトではオフになっています。

次に、例を参照して、リフレッシュ可能な Bean の使用がいかに簡単かを確認します。リフレッシュ可能な Bean 機能を有効にするには、Bean 定義の <lang:language/> 要素に追加の属性を 1 つだけ指定する必要があります。この章の前のに固執する場合、次の例は、リフレッシュ可能な Bean を実現するために Spring XML 構成で何を変更するかを示しています。

<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 の動的言語サポートに関して注意すべき非常に重要なことが 1 つあります。つまり、(現在)コンストラクター引数を動的言語を使用した 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-dynamic-language-backed Bean のをすでにています。次に、別の例を考えます(再び Spring Test スイートの例を使用します)。

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 チームの意見では)ソースファイルごとに 1 つの(パブリック)クラスの標準 Java 規則を考慮する必要があります。

コールバックを使用して Groovy オブジェクトをカスタマイズする

GroovyObjectCustomizer インターフェースは、Groovy-backed 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"/>
Groovy CompilationCustomizer (ImportCustomizer など)または Spring の GroovyObjectCustomizer と同じ場所に完全な 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-backed Bean 定義には、いくつかの(小さな)追加の構成が必要です。Spring は、<lang:bsh> 要素の script-interfaces 属性値で指定されたすべてのインターフェースを実装する JDK 動的プロキシを作成するため、Spring での BeanShell 動的言語サポートの実装は興味深いです(これが、少なくとも 1 つのインターフェースを提供する必要がある理由です)属性の値、およびその結果、BeanShell-backed Bean を使用する場合のインターフェースへのプログラム)。つまり、BeanShell-backed オブジェクトのすべてのメソッド呼び出しは、JDK 動的プロキシ呼び出しメカニズムを通過します。

これで、この章で前述した Messenger インターフェースを実装する BeanShell ベースの Bean を使用した完全に機能する例を示すことができます。再び Messenger インターフェースの定義を示します。

package org.springframework.scripting;

public interface Messenger {

	String getMessage();
}

次の例は、Messenger インターフェースの BeanShell「実装」(ここでは大まかに使用します)を示しています。

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 での動的言語サポートの 2 つの使用例について説明します。

スクリプト化された Spring MVC コントローラー

動的言語でサポートされている Bean を使用することでメリットが得られるクラスの 1 つのグループは、Spring MVC コントローラーのグループです。純粋な Spring MVC アプリケーションでは、Web アプリケーションのナビゲーションフローの大部分は、Spring MVC コントローラー内にカプセル化されたコードによって決定されます。Web アプリケーションのナビゲーションフローやその他のプレゼンテーションレイヤーロジックは、サポートの課題やビジネス要件の変化に対応するために更新する必要があるため、1 つまたは複数の動的言語ソースファイルを編集して確認することで、そのような必要な変更を行う方が簡単な場合があります。実行中のアプリケーションの状態にすぐに反映される変更。

Spring などのプロジェクトで支持されている軽量のアーキテクチャモデルでは、通常、アプリケーションのすべての肉付きのよいビジネスロジックがドメインおよびサービスレイヤークラスに含まれる、非常に薄いプレゼンテーションレイヤーを目指すことを覚えておいてください。動的言語に対応した Bean として Spring MVC コントローラーを開発すると、テキストファイルを編集して保存することでプレゼンテーション層のロジックを変更できます。このような動的言語ソースファイルへの変更は (構成に応じて) 動的言語ソースファイルによってサポートされている 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 を使用したアプリケーション開発のもう 1 つの分野は、動的言語を使用した 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 のスコープを制御できます。(デフォルトのスコープは、「通常の」Bean と同様に singleton です。)

次の例では、scope 属性を使用して、プロトタイプとしてスコープ指定された 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 のスコーピングサポートの詳細については、IoC コンテナーBean スコープを参照してください。

lang XML スキーマ

Spring XML 構成の lang 要素は、Spring コンテナー内の Bean として動的言語(Groovy や BeanShell など)で作成されたオブジェクトの公開を処理します。

これらの要素(および動的言語のサポート)は、動的言語サポートで包括的にカバーされています。このサポートと 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>

その他のリソース

次のリンクは、この章で参照されているさまざまな動的言語に関する詳細なリソースに移動します。