的附加功能ApplicationContext
正如本章介绍中所讨论的,该org.springframework.beans.factory
package 提供了管理和作 bean 的基本功能,包括在
程序化方式。这org.springframework.context
package 添加ApplicationContext
接口,它扩展了BeanFactory
接口,除了扩展其他
接口,以便在更多应用程序中提供附加功能
面向框架的风格。许多人使用ApplicationContext
在完全
声明式时尚,甚至不是以编程方式创建它,而是依赖于
支持类,例如ContextLoader
自动实例化ApplicationContext
作为 Jakarta EE Web 应用程序正常启动过程的一部分。
增强BeanFactory
功能以更面向框架的风格,上下文
package 还提供以下功能:
-
通过
MessageSource
接口。 -
通过
ResourceLoader
接口。 -
事件发布,即实现
ApplicationListener
接口 通过使用ApplicationEventPublisher
接口。 -
加载多个(分层)上下文,让每个上下文都专注于一个 特定层,例如应用程序的 Web 层,通过
HierarchicalBeanFactory
接口。
使用MessageSource
这ApplicationContext
interface 扩展了一个名为MessageSource
和
因此,提供国际化(“i18n”)功能。Spring 还提供了HierarchicalMessageSource
接口,可以分层解析消息。
这些接口共同为 Spring 效果消息提供了基础
分辨率。在这些接口上定义的方法包括:
-
String getMessage(String code, Object[] args, String default, Locale loc)
:基本 用于从MessageSource
.找不到消息时 对于指定的区域设置,将使用默认消息。传入的任何参数都会变成 替换值,使用MessageFormat
标准提供的功能 图书馆。 -
String getMessage(String code, Object[] args, Locale loc)
:本质上与 与前一种方法相同,但有一个区别:不能指定默认消息。如果 找不到消息,则NoSuchMessageException
被抛出。 -
String getMessage(MessageSourceResolvable resolvable, Locale locale)
:所有属性 在前面的方法中使用的也包装在名为MessageSourceResolvable
,您可以将其与此方法一起使用。
当ApplicationContext
加载时,它会自动搜索MessageSource
bean 在上下文中定义。豆子必须有名称messageSource
.如果这样的豆子
找到,则对上述方法的所有调用都委托给消息源。如果没有
消息源,则ApplicationContext
尝试查找包含
同名的豆子。如果是这样,它会使用该 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
实现也是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
哪
存在于类路径的根目录中。这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
) locale,您
将创建名为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
接口注入了
应用程序上下文的MessageSource
创建和配置 Bean 时。
因为Spring的MessageSource 基于 Java 的ResourceBundle ,它不会合并
捆绑包,但仅使用找到的第一个捆绑包。
具有相同基本名称的后续消息包将被忽略。 |
作为替代方案ResourceBundleMessageSource ,Spring 提供了一个ReloadableResourceBundleMessageSource 类。此变体支持相同的捆绑包
文件格式,但比基于标准 JDK 的 JDK 更灵活ResourceBundleMessageSource 实现。特别是,它允许阅读
来自任何 Spring 资源位置(不仅来自类路径)的文件,并支持热
重新加载捆绑属性文件(同时在两者之间有效地缓存它们)。
请参阅ReloadableResourceBundleMessageSource javadoc 了解详情。 |
标准和自定义事件
事件处理ApplicationContext
通过ApplicationEvent
class 和ApplicationListener
接口。如果实现ApplicationListener
接口被部署到上下文中,每次ApplicationEvent
发布到ApplicationContext
,则通知该 bean。
从本质上讲,这是标准的 Observer 设计模式。
从 Spring 4.2 开始,活动基础设施得到了显着改进,并提供了
基于注释的模型以及
能够发布任何任意事件(即不一定
从ApplicationEvent ).当这样的对象被发布时,我们将其包装在
为您举办的活动。 |
下表描述了 Spring 提供的标准事件:
事件 | 解释 |
---|---|
|
发布时 |
|
发布时 |
|
发布时 |
|
发布时 |
|
一个特定于 Web 的事件,告诉所有 Bean HTTP 请求已得到服务。这
请求完成后发布事件。此活动只适用于
使用 Spring 的 |
|
的子类 |
您还可以创建和发布自己的自定义事件。以下示例显示了
简单类,扩展 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。以下内容
示例显示了这样的类:
-
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()
方法可以保持类型安全,避免任何向下转换的需要。
您可以根据需要注册任意数量的事件侦听器,但请注意,默认情况下,事件侦听器会同步接收事件。
这意味着publishEvent()
method 块,直到所有侦听器都处理完事件。
这种同步和单线程方法的一个优点是,当侦听器收到事件时,
如果事务上下文可用,则它在发布者的事务上下文中运行。
如果需要其他事件发布策略,例如,缺省情况下的异步事件处理,
请参阅 javadoc 了解 Spring 的ApplicationEventMulticaster
接口
和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 是
如果有任何应阻止的电子邮件,则调用 a 自定义事件BlockedListEvent
已发布。这blockedListNotifier
bean 被注册为ApplicationListener
并接收BlockedListEvent
,此时它可以
通知有关各方。
Spring 的事件机制专为 Spring Bean 之间的简单通信而设计 在同一应用程序上下文中。但是,对于更复杂的企业 集成需求,单独维护的 Spring Integration 项目提供了 完全支持构建轻量级、面向模式、事件驱动的构建 建立在众所周知的 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...
}
}
不要将此类 bean 定义为惰性,因为ApplicationContext 将尊重这一点,并且不会注册监听事件的方法。 |
方法签名再次声明它侦听的事件类型, 但是,这一次,使用灵活的名称,并且没有实现特定的监听器接口。 只要实际事件类型,还可以通过泛型缩小事件类型 解析其实现层次结构中的泛型参数。
如果你的方法应该监听多个事件,或者如果你想用 参数,也可以在注解本身上指定事件类型。这 以下示例显示了如何执行此作:
-
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 对象 |
实际的 |
|
参数数组 |
root 对象 |
用于调用该方法的参数(作为对象数组)。 |
|
参数名称 |
评估背景 |
特定方法参数的名称。如果名称不可用
(例如,因为代码是在没有 |
|
请注意#root.event
允许您访问底层事件,即使您的方法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
Comments 添加到方法声明中,如以下示例所示:
-
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
实现,实际多播
通过上下文范围发生ApplicationEventMulticaster
在运行时。默认情况下,这是一个SimpleApplicationEventMulticaster
在调用方线程中发布同步事件。
这可以通过“applicationEventMulticaster”bean 定义来替换/自定义,
例如,异步处理所有事件和/或处理侦听器异常:
@Bean
ApplicationEventMulticaster applicationEventMulticaster() {
SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
multicaster.setTaskExecutor(...);
multicaster.setErrorHandler(...);
return multicaster;
}
方便访问低级资源
为了获得最佳使用和理解应用程序上下文,您应该熟悉自己使用 Spring 的Resource
抽象,如参考资料中所述。
应用程序上下文是ResourceLoader
,可用于加载Resource
对象。 一个Resource
本质上是 JDK 的功能更丰富的版本java.net.URL
类。 事实上,实现Resource
包装java.net.URL
哪里 适当。 一个Resource
可以从几乎任何位置以透明的方式获取低级资源,包括从类路径、文件系统位置、任何地方可以使用标准 URL 进行描述,以及其他一些变体。如果资源位置string 是一个没有任何特殊前缀的简单路径,这些资源的来源是特定且适合实际的应用程序上下文类型。
您可以配置部署到应用程序上下文中的 bean 以实现特殊的
回调接口,ResourceLoaderAware
,自动回调
初始化时间,应用程序上下文本身作为ResourceLoader
.
您还可以公开类型Resource
,用于访问静态资源。
它们像任何其他属性一样被注入其中。您可以指定这些Resource
属性为简单String
路径,并依赖于从这些文本自动转换
字符串到实际Resource
对象。
提供给ApplicationContext
构造函数实际上是
资源字符串,并且以简单的形式根据特定的
上下文实现。例如ClassPathXmlApplicationContext
对待简单的
location path 作为类路径位置。您还可以使用位置路径(资源字符串)
使用特殊前缀强制从类路径或 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
实现是一种无作变体,可最大限度地减少开销。
这意味着默认情况下,在应用程序启动期间不会收集任何指标。
Spring Framework 附带了一个用于使用 Java Flight Recorder 跟踪启动步骤的实现:FlightRecorderApplicationStartup
.要使用此变体,您必须配置它的实例
到ApplicationContext
一旦创建。
开发人员还可以使用ApplicationStartup
基础设施(如果他们提供自己的)AbstractApplicationContext
子类,或者如果他们希望收集更精确的数据。
ApplicationStartup 仅在应用程序启动期间使用
核心容器;这绝不是 Java 分析器或
像 Micrometer 这样的指标库。 |
开始收集自定义StartupStep
,组件可以获取ApplicationStartup
实例直接从应用程序上下文中实现,使其组件实现ApplicationStartupAware
,
或要求ApplicationStartup
键入任何注射点。
开发人员不应使用"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
参数。如果参数没有
exist,则监听器使用/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 文件,将
上下文及其在 Jakarta EE RAR 部署中所需的所有 bean 类和库 JAR
单位。这相当于引导一个独立的ApplicationContext
(仅托管
在 Jakarta EE 环境中)能够访问 Jakarta EE 服务器设施。RAR 部署
是部署无头 WAR 文件场景的更自然的替代方案——实际上,
一个没有任何 HTTP 入口点的 WAR 文件,仅用于引导 SpringApplicationContext
在雅加达 EE 环境中。
RAR 部署非常适合不需要 HTTP 入口点但
相反,仅由消息端点和计划作业组成。在这样的上下文中,bean 可以
使用应用程序服务器资源,例如 JTA 事务管理器和 JNDI 绑定的 JDBCDataSource
实例和 JMSConnectionFactory
实例,也可以注册
平台的 JMX 服务器——全部通过 Spring 的标准事务管理和 JNDI
和 JMX 支持设施。应用程序组件也可以与应用程序交互
服务器的 JCAWorkManager
通过 Spring 的TaskExecutor
抽象化。
请参阅SpringContextResourceAdapter
class 用于 RAR 部署中涉及的配置详细信息。
对于将 Spring ApplicationContext 简单部署为 Jakarta EE RAR 文件:
-
包 所有应用程序类都转换为 RAR 文件(这是一个标准 JAR 文件,具有不同的 文件扩展名)。
-
将所有必需的库 JAR 添加到 RAR 存档的根目录中。
-
添加一个
META-INF/ra.xml
部署描述符(如javadoc 的SpringContextResourceAdapter
) 和相应的 Spring XML bean 定义文件(通常META-INF/applicationContext.xml
). -
将生成的 RAR 文件放入您的 应用程序服务器的部署目录。
这种 RAR 部署单元通常是独立的。它们不会暴露组件
对外界,甚至对同一应用程序的其他模块也不行。与
基于 RARApplicationContext 通常通过与其共享的 JMS 目标发生
其他模块。基于 RAR 的ApplicationContext 例如,还可以安排一些作业
或对文件系统中的新文件(或类似文件)做出反应。如果需要允许同步
从外部访问,它可以(例如)导出 RMI 端点,可以使用
由同一台机器上的其他应用程序模块。 |