跳到主要内容

动态语言支持

ChatGPT-4o-mini 中英对照 Dynamic Language Support

Spring 提供了全面的支持,以便使用动态语言(如 Groovy)定义的类和对象与 Spring 一起使用。这种支持使您能够用支持的动态语言编写任意数量的类,并让 Spring 容器透明地实例化、配置和依赖注入生成的对象。

Spring 的脚本支持主要针对 Groovy 和 BeanShell。除了这些特定支持的语言外,JSR-223 脚本机制也支持与任何 JSR-223 兼容的语言提供者集成(从 Spring 4.2 开始),例如 JRuby。

您可以在 Scenarios 中找到此动态语言支持可以立即派上用场的完整示例。

第一个示例

本章的主要内容是详细描述动态语言支持。在深入探讨动态语言支持的所有细节之前,我们先看一个用动态语言定义的 bean 的快速示例。这个第一个 bean 的动态语言是 Groovy。(这个示例的基础来自 Spring 测试套件。如果您想查看其他支持语言中的等效示例,请查看源代码)。

下面的示例展示了 Messenger 接口,Groovy bean 将实现该接口。请注意,这个接口是用普通 Java 定义的。注入了对 Messenger 的引用的依赖对象并不知道底层实现是一个 Groovy 脚本。以下列表展示了 Messenger 接口:

package org.springframework.scripting;

public interface Messenger {

String getMessage();
}
java

以下示例定义了一个依赖于 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...
}
}
java

以下示例在 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
}
groovy
备注

要使用自定义动态语言标签来定义动态语言支持的 bean,您需要在 Spring XML 配置文件的顶部添加 XML Schema 前言。您还需要使用 Spring ApplicationContext 实现作为您的 IoC 容器。使用普通 BeanFactory 实现的动态语言支持的 bean 是支持的,但您必须管理 Spring 内部的管道以实现这一点。

有关基于模式的配置的更多信息,请参见 XML Schema-based Configuration

最后,以下示例展示了影响将 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>
xml

bookingService bean(一个 DefaultBookingService)现在可以像正常一样使用它的私有 messenger 成员变量,因为注入到它的 Messenger 实例是一个 Messenger 实例。这里没有什么特别的 — 只是普通的 Java 和普通的 Groovy。

希望前面的 XML 代码片段是自解释的,但如果不是,也不必过于担心。请继续阅读,以获取关于前面配置的详细原因和背景。

定义由动态语言支持的 Beans

本节准确描述了如何在任何支持的动态语言中定义 Spring 管理的 bean。

注意,本章并不试图解释所支持的动态语言的语法和习惯用法。例如,如果您想使用 Groovy 编写应用程序中的某些类,我们假设您已经了解 Groovy。如果您需要有关动态语言本身的更多详细信息,请参阅本章末尾的 Further Resources

常见概念

使用动态语言支持的 Bean 的步骤如下:

  1. 为动态语言源代码编写测试(自然)。

  2. 然后编写动态语言源代码本身。

  3. 通过在 XML 配置中使用适当的 <lang:language/> 元素定义您的动态语言支持的 bean(您也可以通过使用 Spring API 以编程方式定义这样的 bean,尽管您需要查阅源代码以获取有关如何执行此操作的说明,因为本章不涵盖这种类型的高级配置)。请注意,这是一个迭代步骤。您需要为每个动态语言源文件至少定义一个 bean 定义(尽管多个 bean 定义可以引用同一个源文件)。

前两步(测试和编写你的动态语言源文件)超出了本章的范围。请参阅你选择的动态语言的语言规范和参考手册,继续开发你的动态语言源文件。不过,你首先要阅读本章的其余部分,因为 Spring 的动态语言支持确实对你的动态语言源文件的内容做了一些(小)假设。

The 元素

前面的部分中列表的最后一步涉及定义动态语言支持的 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>
xml

这真的是你需要做的全部。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());
}
}
java

假设在这个例子中,所有对 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
}
}
groovy

当程序运行时,输入暂停之前的输出将是 I Can Do The Frug。在对源文件进行更改并保存后,当程序恢复执行时,对动态语言支持的 Messenger 实现调用 getMessage() 方法的结果是 'I Can Do The Frug'(注意包含了额外的引号)。

对脚本的更改不会触发刷新,如果更改发生在 refresh-check-delay 值的窗口内。对脚本的更改实际上不会被捕捉,直到在动态语言支持的 bean 上调用一个方法。只有在动态语言支持的 bean 上调用方法时,它才会检查其底层脚本源是否已更改。与刷新脚本相关的任何异常(例如遇到编译错误或发现脚本文件已被删除)都会导致致命异常传播到调用代码。

之前描述的可刷新 bean 行为不适用于使用 <lang:inline-script/> 元素表示法定义的动态语言源文件(参见 Inline Dynamic Language Source Files)。此外,它仅适用于可以实际检测到底层源文件更改的 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>
xml

如果我们把围绕在 Spring 配置文件中定义动态语言源是否是良好实践的问题放在一边,<lang:inline-script/> 元素在某些场景中是很有用的。例如,我们可能希望快速将一个 Spring Validator 实现添加到一个 Spring MVC Controller 中。使用内联源,这只是片刻的工作。(请参见 Scripted Validators 以获取此类示例。)

理解动态语言支持的 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
}
groovy
<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>
xml

在实践中,这一限制并不像最初看起来那么重要,因为 setter 注入是绝大多数开发人员所偏爱的注入风格(我们将关于这是否是好事的讨论留到另一天)。

Groovy Beans

本节描述了如何在 Spring 中使用定义在 Groovy 中的 beans。

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);
}
java

以下示例在 Groovy 中实现了 Calculator 接口:

package org.springframework.scripting.groovy

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

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

以下 bean 定义使用在 Groovy 中定义的计算器:

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

最后,以下小应用程序演示了前面的配置:

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));
}
}
java

运行上述程序的结果输出是(毫不奇怪)10。 (有关更有趣的示例,请参阅动态语言展示项目以获取更复杂的示例,或参见本章后面的示例 场景)。

您每个 Groovy 源文件中不得定义超过一个类。虽然在 Groovy 中这完全合法,但这(可以说)是一种不好的实践。为了保持一致的方法,您应该(在 Spring 团队的意见中)遵循每个源文件一个(公共)类的标准 Java 约定。

通过使用回调自定义 Groovy 对象

GroovyObjectCustomizer 接口是一个回调接口,允许您在创建 Groovy 支持的 bean 的过程中插入额外的创建逻辑。例如,该接口的实现可以调用任何所需的初始化方法,设置一些默认属性值,或指定一个自定义的 MetaClass。以下列表显示了 GroovyObjectCustomizer 接口的定义:

public interface GroovyObjectCustomizer {

void customize(GroovyObject goo);
}
java

Spring 框架实例化一个基于 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);
}

}
java

关于 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"/>
xml

如果您不使用 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"/>
xml
备注

您还可以在与 Spring 的 GroovyObjectCustomizer 相同的位置指定一个 Groovy CompilationCustomizer(例如 ImportCustomizer)或甚至一个完整的 Groovy CompilerConfiguration 对象。此外,您可以在 ConfigurableApplicationContext.setClassLoader 级别设置一个具有自定义配置的公共 GroovyClassLoader;这也会导致共享 GroovyClassLoader 的使用,因此在有大量脚本化 bean 的情况下推荐使用(避免每个 bean 使用孤立的 GroovyClassLoader 实例)。

BeanShell Beans

本节描述了如何在 Spring 中使用 BeanShell beans。

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 的 beans 时需要编程接口)。这意味着对基于 BeanShell 的对象的每个方法调用都通过 JDK 动态代理调用机制。

现在我们可以展示一个完整的示例,使用一个基于 BeanShell 的 bean,该 bean 实现了本章前面定义的 Messenger 接口。我们再次展示 Messenger 接口的定义:

package org.springframework.scripting;

public interface Messenger {

String getMessage();
}
java

以下示例展示了 BeanShell 的 Messenger 接口的“实现”(我们在这里宽松地使用这个术语):

String message;

String getMessage() {
return message;
}

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

以下示例展示了定义上述“类”的“实例”的 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>
xml

请参阅 Scenarios 以了解一些您可能希望使用基于 BeanShell 的 bean 的场景。

场景

在脚本语言中定义 Spring 管理的 bean 的可能场景有很多种。这一部分描述了 Spring 中动态语言支持的两个可能用例。

脚本化的 Spring MVC 控制器

可以从使用动态语言支持的 Bean 中受益的一类类是 Spring MVC 控制器。在纯 Spring MVC 应用程序中,Web 应用程序的导航流程在很大程度上是由封装在 Spring MVC 控制器中的代码决定的。随着 Web 应用程序的导航流程和其他表现层逻辑需要更新以响应支持问题或变化的业务需求,通过编辑一个或多个动态语言源文件来实现任何所需的更改,并立即在运行的应用程序状态中反映这些更改,可能会更容易。

请记住,在像 Spring 这样的项目所倡导的轻量级架构模型中,您通常希望拥有一个非常薄的表现层,所有应用程序的核心业务逻辑都包含在领域和服务层类中。将 Spring MVC 控制器开发为动态语言支持的 bean 使您能够通过编辑和保存文本文件来更改表现层逻辑。对这些动态语言源文件的任何更改(根据配置)会自动反映在由动态语言源文件支持的 bean 中。

备注

要实现对动态语言支持的 bean 的任何更改的自动“拾取”,您必须启用“可刷新 bean”功能。有关此功能的完整说明,请参见 Refreshable Beans

以下示例展示了一个使用 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())
}
}
groovy
<lang:groovy id="fortune"
refresh-check-delay="3000"
script-source="/WEB-INF/groovy/FortuneController.groovy">
<lang:property name="fortuneService" ref="fortuneService"/>
</lang:groovy>
xml

脚本验证器

另一个可能受益于动态语言支持的 Spring 应用开发领域是验证。与常规 Java 相比,使用一种松散类型的动态语言(可能还支持内联正则表达式)来表达复杂的验证逻辑可能更容易。

再次,开发作为动态语言支持的 bean 的验证器可以让你通过编辑和保存一个简单的文本文件来更改验证逻辑。任何这样的更改(根据配置)会自动反映在正在运行的应用程序的执行中,并且不需要重启应用程序。

备注

要实现对动态语言支持的 bean 的任何更改的自动“拾取”,您必须启用“可刷新 bean”功能。有关此功能的完整详细说明,请参见 Refreshable Beans

以下示例展示了一个使用 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.")
}
}
groovy

附加细节

这一最后部分包含了一些与动态语言支持相关的附加细节。

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 属性定义一个 Groovy bean,其作用域为 prototype

<?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>
xml

请参见 Bean ScopesThe IoC Container 中,了解 Spring Framework 中作用域支持的完整讨论。

lang XML 模式

lang 元素在 Spring XML 配置中处理将用动态语言(如 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>
xml

进一步资源

以下链接提供了关于本章中提到的各种动态语言的更多资源: