此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.2.0! |
的附加功能ApplicationContext
如本章介绍中所述,org.springframework.beans.factory
package 提供了用于管理和作 bean 的基本功能,包括在
编程方式。这org.springframework.context
软件包会添加ApplicationContext
接口,该接口扩展了BeanFactory
接口,除了扩展其他
接口,以便在更多应用程序中提供额外的功能
面向框架的样式。许多人使用ApplicationContext
在一个完全
声明式方式,甚至不是以编程方式创建它,而是依赖于
支持类,例如ContextLoader
要自动实例化ApplicationContext
作为 Jakarta EE Web 应用程序的正常启动过程的一部分。
增强BeanFactory
功能,上下文
package 还提供以下功能:
-
以 i18n 样式访问消息,通过
MessageSource
接口。 -
通过
ResourceLoader
接口。 -
事件发布,即向实现
ApplicationListener
接口 通过使用ApplicationEventPublisher
接口。 -
加载多个 (分层) 上下文,让每个上下文都专注于一个 特定层(例如应用程序的 Web 层)通过
HierarchicalBeanFactory
接口。
国际化使用MessageSource
这ApplicationContext
interface 扩展了一个名为MessageSource
和
因此,提供国际化 (“i18n”) 功能。Spring 还提供了HierarchicalMessageSource
接口,该接口可以分层解析消息。
这些接口共同为 Spring effects 消息提供了基础
分辨率。在这些接口上定义的方法包括:
-
String getMessage(String code, Object[] args, String default, Locale loc)
: 基本 用于从MessageSource
.未找到消息时 对于指定的区域设置,将使用 default message。传入的任何参数都将变为 replacement 值,使用MessageFormat
标准提供的功能 图书馆。 -
String getMessage(String code, Object[] args, Locale loc)
:基本相同 前一种方法,但有一个区别:不能指定默认消息。如果 找不到该消息,则NoSuchMessageException
被抛出。 -
String getMessage(MessageSourceResolvable resolvable, Locale locale)
:所有属性 使用的方法也被包装在一个名为MessageSourceResolvable
,您可以将其与此方法一起使用。
当ApplicationContext
加载时,它会自动搜索MessageSource
bean 中定义的 bean。该 bean 必须具有名称messageSource
.如果这样的 bean
,则所有对上述方法的调用都会委托给消息源。如果没有
message 源,则ApplicationContext
尝试查找包含
bean 的 bean 的 intent如果是这样,它将使用该 bean 作为MessageSource
.如果ApplicationContext
找不到任何消息源,空的DelegatingMessageSource
实例化,以便能够接受对
方法。
Spring 提供三种MessageSource
实现ResourceBundleMessageSource
,ReloadableResourceBundleMessageSource
和StaticMessageSource
.他们都实现了HierarchicalMessageSource
为了做嵌套
消息。这StaticMessageSource
很少使用,但提供了编程方式
将消息添加到源。以下示例显示了ResourceBundleMessageSource
:
<beans>
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>format</value>
<value>exceptions</value>
<value>windows</value>
</list>
</property>
</bean>
</beans>
该示例假定您有三个名为format
,exceptions
和windows
定义。任何解决消息的请求都是
以 JDK 标准方式处理,通过ResourceBundle
对象。对于
本示例的目的,假设上述两个资源包文件的内容
如下:
# in format.properties
message=Alligators rock!
# in exceptions.properties
argument.required=The {0} argument is required.
下一个示例显示了一个运行MessageSource
功能性。
请记住,所有ApplicationContext
implementations 也是MessageSource
实现,因此可以转换为MessageSource
接口。
-
Java
-
Kotlin
public static void main(String[] args) {
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
String message = resources.getMessage("message", null, "Default", Locale.ENGLISH);
System.out.println(message);
}
fun main() {
val resources = ClassPathXmlApplicationContext("beans.xml")
val message = resources.getMessage("message", null, "Default", Locale.ENGLISH)
println(message)
}
上述程序的结果输出如下:
Alligators rock!
总而言之,MessageSource
在名为beans.xml
哪
存在于 Classpath 的根目录中。这messageSource
bean 定义是指
通过其basenames
财产。这三个文件是
在列表中传递给basenames
属性作为文件存在于
classpath 并调用format.properties
,exceptions.properties
和windows.properties
分别。
下一个示例显示了传递给消息查找的参数。这些参数是
转换为String
对象并插入到查找消息的占位符中。
<beans>
<!-- this MessageSource is being used in a web application -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="exceptions"/>
</bean>
<!-- lets inject the above MessageSource into this POJO -->
<bean id="example" class="com.something.Example">
<property name="messages" ref="messageSource"/>
</bean>
</beans>
-
Java
-
Kotlin
public class Example {
private MessageSource messages;
public void setMessages(MessageSource messages) {
this.messages = messages;
}
public void execute() {
String message = this.messages.getMessage("argument.required",
new Object [] {"userDao"}, "Required", Locale.ENGLISH);
System.out.println(message);
}
}
class Example {
lateinit var messages: MessageSource
fun execute() {
val message = messages.getMessage("argument.required",
arrayOf("userDao"), "Required", Locale.ENGLISH)
println(message)
}
}
调用execute()
方法如下:
The userDao argument is required.
关于国际化(“i18n”),Spring 的各种MessageSource
实现遵循与标准 JDK 相同的区域设置解析和回退规则ResourceBundle
.简而言之,继续这个例子messageSource
定义
以前,如果要解决针对英国 (en-GB
) 区域设置中,您
将创建名为format_en_GB.properties
,exceptions_en_GB.properties
和windows_en_GB.properties
分别。
通常,区域设置解析由 应用。在以下示例中,(英国)消息所针对的区域设置 resolved 手动指定:
# in exceptions_en_GB.properties argument.required=Ebagum lad, the ''{0}'' argument is required, I say, required.
-
Java
-
Kotlin
public static void main(final String[] args) {
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
String message = resources.getMessage("argument.required",
new Object [] {"userDao"}, "Required", Locale.UK);
System.out.println(message);
}
fun main() {
val resources = ClassPathXmlApplicationContext("beans.xml")
val message = resources.getMessage("argument.required",
arrayOf("userDao"), "Required", Locale.UK)
println(message)
}
运行上述程序的结果输出如下:
Ebagum lad, the 'userDao' argument is required, I say, required.
您还可以使用MessageSourceAware
接口获取对任何MessageSource
这已经被定义过了。在ApplicationContext
实现MessageSourceAware
interface 注入了
应用程序上下文的MessageSource
创建和配置 Bean 时。
因为 Spring 的MessageSource 基于 Java 的ResourceBundle ,则不会合并
具有相同基本名称的捆绑包,但将仅使用找到的第一个捆绑包。
具有相同基本名称的后续消息包将被忽略。 |
作为ResourceBundleMessageSource 中,Spring 提供了一个ReloadableResourceBundleMessageSource 类。此变体支持相同的捆绑包
文件格式,但比基于 JDK 的标准 JDK 更灵活ResourceBundleMessageSource 实现。特别是,它允许读取
文件(不仅来自 Classpath),并支持热
重新加载 bundle 属性文件(同时在两者之间有效地缓存它们)。
请参阅ReloadableResourceBundleMessageSource javadoc 了解详细信息。 |
标准事件和自定义事件
事件处理ApplicationContext
通过ApplicationEvent
类和ApplicationListener
接口。如果实现ApplicationListener
interface 部署到上下文中,则每次ApplicationEvent
发布到ApplicationContext
,该 bean 会收到通知。
从本质上讲,这是标准的 Observer 设计模式。
从 Spring 4.2 开始,活动基础设施得到了显著改进,并提供
基于注释的模型以及
能够发布任何任意事件(即,不一定
延伸自ApplicationEvent ).当这样的对象被发布时,我们将其包装在
活动。 |
下表描述了 Spring 提供的标准事件:
事件 | 解释 |
---|---|
|
发布时 |
|
发布时 |
|
发布时 |
|
发布时 |
|
一个特定于 Web 的事件,告诉所有 bean HTTP 请求已得到处理。这
事件在请求完成后发布。此活动仅适用于
使用 Spring 的 |
|
的子类 |
您还可以创建和发布自己的自定义事件。以下示例显示了
simple 类,该类扩展了 Spring 的ApplicationEvent
基类:
-
Java
-
Kotlin
public class BlockedListEvent extends ApplicationEvent {
private final String address;
private final String content;
public BlockedListEvent(Object source, String address, String content) {
super(source);
this.address = address;
this.content = content;
}
// accessor and other methods...
}
class BlockedListEvent(source: Any,
val address: String,
val content: String) : ApplicationEvent(source)
发布自定义ApplicationEvent
,调用publishEvent()
方法在ApplicationEventPublisher
.通常,这是通过创建一个实现ApplicationEventPublisherAware
并将其注册为 Spring bean。以下内容
example 显示了这样的类:
-
Java
-
Kotlin
public class EmailService implements ApplicationEventPublisherAware {
private List<String> blockedList;
private ApplicationEventPublisher publisher;
public void setBlockedList(List<String> blockedList) {
this.blockedList = blockedList;
}
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
public void sendEmail(String address, String content) {
if (blockedList.contains(address)) {
publisher.publishEvent(new BlockedListEvent(this, address, content));
return;
}
// send email...
}
}
class EmailService : ApplicationEventPublisherAware {
private lateinit var blockedList: List<String>
private lateinit var publisher: ApplicationEventPublisher
fun setBlockedList(blockedList: List<String>) {
this.blockedList = blockedList
}
override fun setApplicationEventPublisher(publisher: ApplicationEventPublisher) {
this.publisher = publisher
}
fun sendEmail(address: String, content: String) {
if (blockedList!!.contains(address)) {
publisher!!.publishEvent(BlockedListEvent(this, address, content))
return
}
// send email...
}
}
在配置时, Spring 容器检测到EmailService
实现ApplicationEventPublisherAware
并自动调用setApplicationEventPublisher()
.实际上,传入的参数是 Spring
容器本身。您正在通过其ApplicationEventPublisher
接口。
要接收自定义ApplicationEvent
中,您可以创建一个实现ApplicationListener
并将其注册为 Spring bean。以下示例
显示了这样的类:
-
Java
-
Kotlin
public class BlockedListNotifier implements ApplicationListener<BlockedListEvent> {
private String notificationAddress;
public void setNotificationAddress(String notificationAddress) {
this.notificationAddress = notificationAddress;
}
public void onApplicationEvent(BlockedListEvent event) {
// notify appropriate parties via notificationAddress...
}
}
class BlockedListNotifier : ApplicationListener<BlockedListEvent> {
lateinit var notificationAddress: String
override fun onApplicationEvent(event: BlockedListEvent) {
// notify appropriate parties via notificationAddress...
}
}
请注意,ApplicationListener
通常使用自定义事件的类型 (BlockedListEvent
在前面的示例中)。
这意味着onApplicationEvent()
method 可以保持类型安全,无需进行 downcast。
您可以根据需要注册任意数量的事件侦听器,但请注意,默认情况下,事件侦听器同步接收事件。
这意味着publishEvent()
method 阻塞,直到所有侦听器都处理完事件。
这种同步和单线程方法的一个优点是,当侦听器接收到事件时,
如果事务上下文可用,它将在 publisher 的事务上下文中运行。
如果需要其他事件发布策略,例如,默认情况下为异步事件处理,
请参阅 Spring 的 javadocApplicationEventMulticaster
接口
和SimpleApplicationEventMulticaster
实现
对于可以应用于自定义 “applicationEventMulticaster” bean 定义的配置选项。
在这些情况下,不会传播 ThreadLocals 和日志记录上下文以进行事件处理。
看这@EventListener
可观测性部分了解有关可观测性问题的更多信息。
以下示例显示了用于注册和配置每个 上面的类:
<bean id="emailService" class="example.EmailService">
<property name="blockedList">
<list>
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
</list>
</property>
</bean>
<bean id="blockedListNotifier" class="example.BlockedListNotifier">
<property name="notificationAddress" value="[email protected]"/>
</bean>
<!-- optional: a custom ApplicationEventMulticaster definition -->
<bean id="applicationEventMulticaster" class="org.springframework.context.event.SimpleApplicationEventMulticaster">
<property name="taskExecutor" ref="..."/>
<property name="errorHandler" ref="..."/>
</bean>
把它们放在一起,当sendEmail()
方法emailService
bean 是
如果有任何应阻止的电子邮件消息,则调用一个BlockedListEvent
发布。这blockedListNotifier
bean 注册为ApplicationListener
并接收BlockedListEvent
,此时它可以
通知相关方。
Spring 的事件机制是为 Spring bean 之间的简单通信而设计的 在同一应用程序上下文中。但是,对于更复杂的企业 集成需求,单独维护的 Spring 集成项目提供了 完全支持构建轻量级、面向模式、事件驱动的 构建在众所周知的 Spring 编程模型之上的架构。 |
基于注释的事件侦听器
您可以使用@EventListener
注解。这BlockedListNotifier
可以重写如下:
-
Java
-
Kotlin
public class BlockedListNotifier {
private String notificationAddress;
public void setNotificationAddress(String notificationAddress) {
this.notificationAddress = notificationAddress;
}
@EventListener
public void processBlockedListEvent(BlockedListEvent event) {
// notify appropriate parties via notificationAddress...
}
}
class BlockedListNotifier {
lateinit var notificationAddress: String
@EventListener
fun processBlockedListEvent(event: BlockedListEvent) {
// notify appropriate parties via notificationAddress...
}
}
方法签名再次声明它监听的事件类型, 但是,这一次,使用灵活的名称,并且没有实现特定的侦听器接口。 事件类型也可以通过泛型缩小范围,只要实际的事件类型 在其 implementation hierarchy 中解析泛型参数。
如果你的方法应该监听多个事件,或者你想用 no 参数,也可以在 Annotation 本身上指定事件类型。这 以下示例显示了如何执行此作:
-
Java
-
Kotlin
@EventListener({ContextStartedEvent.class, ContextRefreshedEvent.class})
public void handleContextStart() {
// ...
}
@EventListener(ContextStartedEvent::class, ContextRefreshedEvent::class)
fun handleContextStart() {
// ...
}
还可以使用condition
属性
的注释中定义SpEL
表达,它应该匹配
以实际调用特定事件的方法。
下面的示例展示了如何重写我们的通知器,以便仅在content
属性等于my-event
:
-
Java
-
Kotlin
@EventListener(condition = "#blEvent.content == 'my-event'")
public void processBlockedListEvent(BlockedListEvent blEvent) {
// notify appropriate parties via notificationAddress...
}
@EventListener(condition = "#blEvent.content == 'my-event'")
fun processBlockedListEvent(blEvent: BlockedListEvent) {
// notify appropriate parties via notificationAddress...
}
每SpEL
expression 根据专用上下文进行计算。下表列出了
项,以便您可以将它们用于条件事件处理:
名字 | 位置 | 描述 | 例 |
---|---|---|---|
事件 |
root 对象 |
实际的 |
|
Arguments 数组 |
root 对象 |
用于调用方法的参数(作为对象数组)。 |
|
参数名称 |
评估上下文 |
特定方法参数的名称。如果名称不可用
(例如,由于代码是在编译时没有使用 |
|
请注意,#root.event
允许您访问底层事件,即使您的方法
signature 实际上是指已发布的任意对象。
如果您需要发布事件作为处理其他事件的结果,则可以更改 method signature 返回应发布的事件,如下例所示:
-
Java
-
Kotlin
@EventListener
public ListUpdateEvent handleBlockedListEvent(BlockedListEvent event) {
// notify appropriate parties via notificationAddress and
// then publish a ListUpdateEvent...
}
@EventListener
fun handleBlockedListEvent(event: BlockedListEvent): ListUpdateEvent {
// notify appropriate parties via notificationAddress and
// then publish a ListUpdateEvent...
}
异步侦听器不支持此功能。 |
这handleBlockedListEvent()
方法发布一个新的ListUpdateEvent
对于每个BlockedListEvent
它处理。如果需要发布多个事件,可以返回
一个Collection
或事件数组。
异步侦听器
如果您希望特定侦听器异步处理事件,则可以重用定期@Async
支持.
以下示例显示了如何执行此作:
-
Java
-
Kotlin
@EventListener
@Async
public void processBlockedListEvent(BlockedListEvent event) {
// BlockedListEvent is processed in a separate thread
}
@EventListener
@Async
fun processBlockedListEvent(event: BlockedListEvent) {
// BlockedListEvent is processed in a separate thread
}
使用异步事件时,请注意以下限制:
-
如果异步事件侦听器抛出
Exception
,它不会传播到 访客。看AsyncUncaughtExceptionHandler
了解更多详情。 -
异步事件侦听器方法无法通过返回 价值。如果您需要发布另一个事件作为处理的结果,请注入
ApplicationEventPublisher
以手动发布事件。 -
默认情况下,不会传播 ThreadLocals 和日志记录上下文以进行事件处理。 看这
@EventListener
可观测性部分了解有关可观测性问题的更多信息。
对侦听器进行排序
如果需要先调用一个侦听器,然后再调用另一个侦听器,则可以添加@Order
注解添加到方法声明中,如下例所示:
-
Java
-
Kotlin
@EventListener
@Order(42)
public void processBlockedListEvent(BlockedListEvent event) {
// notify appropriate parties via notificationAddress...
}
@EventListener
@Order(42)
fun processBlockedListEvent(event: BlockedListEvent) {
// notify appropriate parties via notificationAddress...
}
泛型事件
您还可以使用泛型来进一步定义事件的结构。考虑使用EntityCreatedEvent<T>
哪里T
是已创建的实际实体的类型。例如,您
可以创建以下侦听器定义以仅接收EntityCreatedEvent
对于Person
:
-
Java
-
Kotlin
@EventListener
public void onPersonCreated(EntityCreatedEvent<Person> event) {
// ...
}
@EventListener
fun onPersonCreated(event: EntityCreatedEvent<Person>) {
// ...
}
由于类型擦除,仅当触发的事件解析泛型
事件侦听器过滤的参数(即,类似于class PersonCreatedEvent extends EntityCreatedEvent<Person> { … }
).
在某些情况下,如果所有事件都遵循相同的
结构(如上例中的事件所示)。在这种情况下,
您可以实施ResolvableTypeProvider
引导框架超越运行时
环境提供。以下事件演示如何执行此作:
-
Java
-
Kotlin
public class EntityCreatedEvent<T> extends ApplicationEvent implements ResolvableTypeProvider {
public EntityCreatedEvent(T entity) {
super(entity);
}
@Override
public ResolvableType getResolvableType() {
return ResolvableType.forClassWithGenerics(getClass(), ResolvableType.forInstance(getSource()));
}
}
class EntityCreatedEvent<T>(entity: T) : ApplicationEvent(entity), ResolvableTypeProvider {
override fun getResolvableType(): ResolvableType? {
return ResolvableType.forClassWithGenerics(javaClass, ResolvableType.forInstance(getSource()))
}
}
这不仅适用于ApplicationEvent 但是您作为
一个事件。 |
最后,与经典一样ApplicationListener
implementations,实际的多播
通过上下文范围的ApplicationEventMulticaster
在运行时。默认情况下,这是一个SimpleApplicationEventMulticaster
在调用方线程中使用同步事件发布。
这可以通过 “applicationEventMulticaster” bean 定义来替换/自定义。
例如,用于异步处理所有事件和/或处理侦听器异常:
@Bean
ApplicationEventMulticaster applicationEventMulticaster() {
SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
multicaster.setTaskExecutor(...);
multicaster.setErrorHandler(...);
return multicaster;
}
方便访问底层资源
为了最佳地使用和理解应用程序上下文,您应该熟悉
您自己与 Spring 的Resource
abstraction 的 API 方法,如 参考资料 中所述。
应用程序上下文是一个ResourceLoader
,可用于加载Resource
对象。
一个Resource
本质上是 JDK 的一个功能更丰富的版本java.net.URL
类。
事实上,Resource
包装java.net.URL
哪里
适当。一个Resource
可以从
透明方式,包括从 Classpath、文件系统位置、任何位置
decpreable 替换为标准 URL 和其他一些变体。如果资源位置
string 是一个没有任何特殊前缀的简单路径,这些资源的来源是
特定于实际的应用程序上下文类型。
您可以配置部署到应用程序上下文中的 Bean 来实现特殊的
callback 接口,ResourceLoaderAware
,以自动回调
初始化时间,应用程序上下文本身作为ResourceLoader
.
您还可以公开Resource
,用于访问静态资源。
它们像任何其他属性一样被注入其中。您可以指定这些Resource
properties as simpleString
paths 并依赖于这些文本的自动转换
strings 到 actualResource
对象。
提供给ApplicationContext
constructor 实际上是
资源字符串,并且以简单形式,根据特定的
context 实现。例如ClassPathXmlApplicationContext
处理简单的
location path 作为 Classpath 位置。您还可以使用位置路径(资源字符串)
替换为特殊前缀来强制从 Classpath 或 URL 加载定义,
无论实际的上下文类型如何。
应用程序启动跟踪
这ApplicationContext
管理 Spring 应用程序的生命周期,并提供丰富的
围绕组件的编程模型。因此,复杂的应用程序可以具有同等的
复杂组件图和启动阶段。
使用特定指标跟踪应用程序启动步骤有助于了解位置 时间花在启动阶段,但它也可以用作一种更好的方式 了解整个上下文生命周期。
这AbstractApplicationContext
(及其子类)使用ApplicationStartup
,它收集StartupStep
有关各个启动阶段的数据:
-
应用程序上下文生命周期(基础包扫描、配置类管理)
-
Bean 生命周期(实例化、智能初始化、后处理)
-
应用程序事件处理
以下是AnnotationConfigApplicationContext
:
-
Java
-
Kotlin
// create a startup step and start recording
StartupStep scanPackages = getApplicationStartup().start("spring.context.base-packages.scan");
// add tagging information to the current step
scanPackages.tag("packages", () -> Arrays.toString(basePackages));
// perform the actual phase we're instrumenting
this.scanner.scan(basePackages);
// end the current step
scanPackages.end();
// create a startup step and start recording
val scanPackages = getApplicationStartup().start("spring.context.base-packages.scan")
// add tagging information to the current step
scanPackages.tag("packages", () -> Arrays.toString(basePackages))
// perform the actual phase we're instrumenting
this.scanner.scan(basePackages)
// end the current step
scanPackages.end()
应用程序上下文已经通过多个步骤进行了检测。 记录后,可以使用特定工具收集、显示和分析这些启动步骤。 有关现有启动步骤的完整列表,您可以查看专门的附录部分。
默认的ApplicationStartup
implementation 是 no-op 变体,以实现最小的开销。
这意味着默认情况下,在应用程序启动期间不会收集任何指标。
Spring Framework 附带了一个用于使用 Java Flight Recorder 跟踪启动步骤的实现:FlightRecorderApplicationStartup
.要使用此变体,您必须配置它的实例
到ApplicationContext
一旦创建。
开发人员还可以使用ApplicationStartup
基础设施(如果他们提供自己的AbstractApplicationContext
子类,或者如果他们希望收集更精确的数据。
ApplicationStartup 仅用于应用程序启动期间,并且
核心容器;这绝不是 Java 分析器或
度量库,如 Micrometer。 |
开始收集自定义StartupStep
,组件可以获取ApplicationStartup
实例,让他们的组件实现ApplicationStartupAware
,
或请求ApplicationStartup
键入 on any injection point。
开发人员不应使用"spring.*" 命名空间。
此命名空间保留供 Spring 内部使用,并且可能会发生更改。 |
用于 Web 应用程序的便捷 ApplicationContext 实例化
您可以创建ApplicationContext
实例,例如,使用ContextLoader
.当然,您也可以创建ApplicationContext
实例
以编程方式使用ApplicationContext
实现。
您可以注册一个ApplicationContext
通过使用ContextLoaderListener
,作为
以下示例显示:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
侦听器检查contextConfigLocation
参数。如果参数不
存在,则侦听器使用/WEB-INF/applicationContext.xml
作为默认值。当
参数确实存在,则侦听器会分隔String
通过使用预定义的
分隔符(逗号、分号和空格),并将值用作其中
搜索应用程序上下文。还支持 Ant 样式的路径模式。
例如:/WEB-INF/*Context.xml
(对于名称以Context.xml
,它们位于WEB-INF
目录)和/WEB-INF/**/*Context.xml
(对于WEB-INF
).
部署 SpringApplicationContext
作为 Jakarta EE RAR 文件
可以部署 SpringApplicationContext
作为 RAR 文件,将
Context 及其所有必需的 bean 类和库 JAR 在 Jakarta EE RAR 部署中
单位。这相当于引导一个独立的ApplicationContext
(仅托管
在 Jakarta EE 环境中)能够访问 Jakarta EE 服务器设施。RAR 部署
是部署无头 WAR 文件方案的更自然的替代方案 — 实际上,
一个没有任何 HTTP 入口点的 WAR 文件,仅用于引导 SpringApplicationContext
在 Jakarta EE 环境中。
RAR 部署非常适合不需要 HTTP 入口点但
而是由消息终端节点和计划作业组成。在这种情况下,bean 可以
使用应用程序服务器资源,比如 JTA 事务管理器和 JNDI 绑定的 JDBCDataSource
实例和 JMSConnectionFactory
实例,也可以注册
平台的 JMX 服务器 — 全部通过 Spring 的标准事务管理和 JNDI
和 JMX 支持工具。应用程序组件还可以与应用程序交互
服务器的 JCAWorkManager
通过 Spring 的TaskExecutor
抽象化。
请参阅SpringContextResourceAdapter
类,了解 RAR 部署中涉及的配置详细信息。
要将 Spring ApplicationContext 简单部署为 Jakarta EE RAR 文件:
-
包 所有应用程序类都合并到一个 RAR 文件(这是一个标准、JAR 文件,具有不同的 文件扩展名)。
-
将所有必需的库 JAR 添加到 RAR 存档的根目录中。
-
添加
META-INF/ra.xml
部署描述符(如javadoc 的SpringContextResourceAdapter
) 和相应的 Spring XML bean 定义文件(通常为META-INF/applicationContext.xml
). -
将生成的 RAR 文件拖放到 Application Server 的部署目录。
此类 RAR 部署单元通常是独立的。它们不暴露组件
对外界,甚至对同一应用程序的其他模块也不例外。与
基于 RARApplicationContext 通常通过与之共享的 JMS 目标发生
其他模块。基于 RAR 的ApplicationContext 例如,还可以安排一些作业
或对文件系统中的新文件(或类似文件)做出反应。如果需要允许同步
从外部访问,它可以(例如)导出 RMI 端点,这些端点可以使用
通过同一台计算机上的其他应用程序模块。 |