正如本章介绍中所讨论的,该软件包提供了管理和操作 Bean 的基本功能,包括
程序化方式。该包添加了 ApplicationContext
接口,该接口除了扩展其他接口外,还扩展了接口。
接口,可在更多应用程序中提供附加功能
面向框架的风格。许多人完全使用
声明式时尚,甚至不是以编程方式创建它,而是依赖于
支持类,例如在 Jakarta EE Web 应用程序的正常启动过程中自动实例化。org.springframework.beans.factory
org.springframework.context
BeanFactory
ApplicationContext
ContextLoader
ApplicationContext
为了以更面向框架的风格增强功能,上下文
软件包还提供以下功能:BeanFactory
-
通过界面访问 i18n 样式的消息。
MessageSource
-
通过界面访问资源,例如 URL 和文件。
ResourceLoader
-
事件发布,即对实现接口的 Bean, 通过使用界面。
ApplicationListener
ApplicationEventPublisher
-
加载多个(分层)上下文,让每个上下文都集中在一个上下文上 特定层,例如应用程序的 Web 层,通过接口。
HierarchicalBeanFactory
国际化使用MessageSource
该接口扩展了一个名为 and 的接口,
因此,提供国际化(“I18N”)功能。Spring 还提供了接口,可以分层解析消息。
这些接口共同提供了 Spring 效果消息的基础
分辨率。在这些接口上定义的方法包括:ApplicationContext
MessageSource
HierarchicalMessageSource
-
String getMessage(String code, Object[] args, String default, Locale loc)
:基本款 用于从 中检索消息的方法。当找不到任何消息时 对于指定的区域设置,使用默认消息。传入的任何参数都将成为 替换值,使用标准提供的功能 图书馆。MessageSource
MessageFormat
-
String getMessage(String code, Object[] args, Locale loc)
:基本相同 与前一种方法不同,但有一个区别:无法指定默认消息。如果 找不到消息,抛出 A。NoSuchMessageException
-
String getMessage(MessageSourceResolvable resolvable, Locale locale)
: 所有属性 在前面的方法中使用的也包装在名为 的类中,可以与此方法一起使用。MessageSourceResolvable
当加载 an 时,它会自动搜索上下文中定义的 bean。Bean 必须具有名称 。如果这样的豆子
找到,则对上述方法的所有调用都将委托给消息源。如果没有
找到消息源,尝试查找包含
同名的 Bean。如果是这样,它将使用该 Bean 作为 .如果找不到任何消息源,则实例化一个空,以便能够接受对
上面定义的方法。ApplicationContext
MessageSource
messageSource
ApplicationContext
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>
该示例假定您有三个名为 的资源包,并在类路径中定义。任何解析消息的请求都是
以 JDK 标准的方式处理通过对象解析消息。对于
在本示例中,假定上述两个资源包文件的内容
具体如下:format
exceptions
windows
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!
总而言之,在一个名为 的文件中定义了 ,该文件
存在于类路径的根目录中。bean 定义是指
通过其属性的资源包数。这三个文件是
在列表中传递给属性的文件作为文件存在于
classpath 和 分别称为 、 和 。MessageSource
beans.xml
messageSource
basenames
basenames
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 的各种实现遵循与标准 JDK 相同的语言环境解析和回退规则。简而言之,并继续定义的示例
以前,如果要解析针对英国 () 区域设置的消息,则
将分别创建名为 、 和 的文件。MessageSource
ResourceBundle
messageSource
en-GB
format_en_GB.properties
exceptions_en_GB.properties
windows_en_GB.properties
通常,区域设置分辨率由环境的周围环境管理。 应用。在以下示例中,(英国)消息所针对的区域设置 已解决,手动指定:
# 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.
您还可以使用该接口获取对任何已定义的引用。在实现接口的 an 中定义的任何 bean 都会注入
创建和配置 Bean 时的应用程序上下文。MessageSourceAware
MessageSource
ApplicationContext
MessageSourceAware
MessageSource
因为 Spring 是基于 Java 的,所以它不会合并
具有相同基本名称的捆绑包,但仅使用找到的第一个捆绑包。
具有相同基本名称的后续消息包将被忽略。MessageSource ResourceBundle |
作为 的替代方法,Spring 提供了一个类。此变体支持相同的捆绑包
文件格式,但比基于 JDK 的标准实现更灵活。特别是,它允许阅读
来自任何 Spring 资源位置的文件(不仅来自类路径),并支持热
重新加载捆绑属性文件(同时在两者之间有效地缓存它们)。
有关详细信息,请参阅 ReloadableResourceBundleMessageSource javadoc。ResourceBundleMessageSource ReloadableResourceBundleMessageSource ResourceBundleMessageSource |
标准事件和自定义事件
中的事件处理是通过类和接口提供的。如果实现接口的 Bean 部署到上下文中,则每次将 an 发布到 时,都会通知该 bean。
从本质上讲,这是标准的 Observer 设计模式。ApplicationContext
ApplicationEvent
ApplicationListener
ApplicationListener
ApplicationEvent
ApplicationContext
从春季 4.2 开始,活动基础设施得到了显着改进,并提供
基于注释的模型以及
能够发布任何任意事件(即,不一定
从 扩展 )。当这样的对象被发布时,我们将其包装在一个
活动。ApplicationEvent |
下表描述了 Spring 提供的标准事件:
事件 | 解释 |
---|---|
|
在初始化或刷新时发布(例如,由
使用接口上的方法)。
在这里,“初始化”意味着加载所有 Bean,检测后处理器 Bean
并激活,单例被预先实例化,并且对象是
准备使用。只要上下文尚未关闭,就可以触发刷新
多次,前提是所选对象实际上支持此类
“热”刷新。例如,支持热刷新,但不支持。 |
|
在使用接口上的方法启动时发布。在这里,“started”表示所有 Bean 都接收到显式的启动信号。通常,此信号用于重新启动 Bean
在显式停止之后,但它也可用于启动尚未停止的组件
配置为自动启动(例如,尚未启动的组件)
初始化)。 |
|
在使用接口上的方法停止时发布。在这里,“停止”意味着所有 Bean 都接收到明确的停止信号。停止的上下文可以通过调用重新启动。 |
|
使用以下方法关闭时发布
在接口上或通过 JVM 关闭钩子。这里
“关闭”意味着所有单例 Bean 都将被销毁。关闭上下文后,
它已达到使用寿命,无法刷新或重新启动。 |
|
特定于 Web 的事件,告知所有 Bean 已处理 HTTP 请求。这
事件在请求完成后发布。此活动只适用于
使用 Spring 的 Web 应用程序。 |
|
其子类添加特定于 Servlet 的上下文信息。 |
您还可以创建和发布自己的自定义事件。以下示例显示了
扩展 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)
若要发布自定义项,请在 .通常,这是通过创建一个实现并将其注册为 Spring Bean 的类来完成的。以下
示例显示了这样的类:ApplicationEvent
publishEvent()
ApplicationEventPublisher
ApplicationEventPublisherAware
-
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()
ApplicationEventPublisher
要接收自定义 ,您可以创建一个实现的类并将其注册为 Spring Bean。以下示例
显示这样的类:ApplicationEvent
ApplicationListener
-
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...
}
}
请注意,它通常使用自定义事件的类型进行参数化(在前面的示例中)。
这意味着该方法可以保持类型安全,避免任何向下转换的需要。
您可以根据需要注册任意数量的事件侦听器,但请注意,默认情况下,事件侦听器会同步接收事件。
这意味着该方法将阻塞,直到所有侦听器都完成对事件的处理。
这种同步和单线程方法的一个优点是,当侦听器接收到事件时,
如果事务上下文可用,它将在发布者的事务上下文中运行。
如果需要其他事件发布策略,例如默认的异步事件处理,
请参阅 Spring 的 ApplicationEventMulticaster
接口的 javadoc
和 SimpleApplicationEventMulticaster
实现
用于可应用于自定义“applicationEventMulticaster”Bean 定义的配置选项。
在这些情况下,不会为事件处理传播 ThreadLocals 和日志记录上下文。
有关可观测性问题的更多信息,请参阅@EventListener
可观测性部分。ApplicationListener
BlockedListEvent
onApplicationEvent()
publishEvent()
以下示例显示了用于注册和配置每个 以上课程:
<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>
把它们放在一起,当豆子的方法
调用时,如果存在任何应阻止的电子邮件,则会发布该类型的自定义事件。Bean 被注册为 并接收 ,此时它可以
通知有关各方。sendEmail()
emailService
BlockedListEvent
blockedListNotifier
ApplicationListener
BlockedListEvent
Spring 的事件机制专为 Spring Bean 之间的简单通信而设计 在同一应用程序上下文中。但是,对于更复杂的企业 集成需求,单独维护的 Spring Integration 项目提供 完全支持构建轻量级、面向模式、事件驱动的 建立在著名的 Spring 编程模型之上的体系结构。 |
基于注释的事件侦听器
您可以使用注释在托管 Bean 的任何方法上注册事件侦听器。可以按如下方式重写:@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...
}
}
方法签名再次声明它侦听的事件类型, 但是,这一次,使用灵活的名称,并且没有实现特定的侦听器接口。 事件类型也可以通过泛型缩小范围,只要实际事件类型 解析其实现层次结构中的泛型参数。
如果你的方法应该侦听多个事件,或者如果你想用 no 来定义它 参数,也可以在注解本身上指定事件类型。这 以下示例演示如何执行此操作:
-
Java
-
Kotlin
@EventListener({ContextStartedEvent.class, ContextRefreshedEvent.class})
public void handleContextStart() {
// ...
}
@EventListener(ContextStartedEvent::class, ContextRefreshedEvent::class)
fun handleContextStart() {
// ...
}
还可以使用属性添加其他运行时筛选
定义 SpEL
表达式的注释,该表达式应匹配
以实际调用特定事件的方法。condition
以下示例显示了如何重写我们的通知程序,使其仅在事件的属性等于 时才调用: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
名字 | 位置 | 描述 | 例 |
---|---|---|---|
事件 |
root 对象 |
实际的 . |
|
参数数组 |
root 对象 |
用于调用方法的参数(作为对象数组)。 |
|
参数名称 |
评估上下文 |
任何方法参数的名称。如果由于某种原因,名称不可用
(例如,因为编译后的字节码中没有调试信息)、单个
参数也可以使用语法,其中代表
参数索引(从 0 开始)。 |
|
请注意,即使方法允许你访问基础事件,也是如此
签名实际上是指已发布的任意对象。#root.event
如果需要发布一个事件作为处理另一个事件的结果,则可以将 方法签名返回应发布的事件,如以下示例所示:
-
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
}
使用异步事件时,请注意以下限制:
-
如果异步事件侦听器抛出 ,则不会传播到 访客。有关详细信息,请参阅
AsyncUncaughtExceptionHandler
。Exception
-
异步事件侦听器方法无法通过返回 价值。如果需要发布另一个事件作为处理结果,请注入
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...
}
通用事件
您还可以使用泛型来进一步定义事件的结构。请考虑使用 where 是已创建的实际实体的类型。例如,你
可以创建以下侦听器定义以仅接收: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 |
最后,与经典实现一样,实际的组播
在运行时通过上下文范围发生。默认情况下,这是调用方线程中的同步事件发布。
这可以通过“applicationEventMulticaster”bean 定义进行替换/定制,
例如,用于异步处理所有事件和/或处理侦听器异常:ApplicationListener
ApplicationEventMulticaster
SimpleApplicationEventMulticaster
@Bean
ApplicationEventMulticaster applicationEventMulticaster() {
SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
multicaster.setTaskExecutor(...);
multicaster.setErrorHandler(...);
return multicaster;
}
方便访问低级资源
为了获得最佳使用和对应用程序上下文的理解,您应该熟悉
你自己使用 Spring 的抽象,如 参考资料 中所述。Resource
应用程序上下文是 ,可用于加载对象。
A 本质上是 JDK 类的功能更丰富的版本。
实际上,包装实例的实现 ,其中
适当。A 可以从 A 中的几乎任何位置获取低级资源
透明的时尚,包括来自类路径、文件系统位置、任何地方
可以使用标准 URL 和其他一些变体进行描述。如果资源位置
string 是一条没有任何特殊前缀的简单路径,这些资源的来源是
特定且适合实际应用程序上下文类型。ResourceLoader
Resource
Resource
java.net.URL
Resource
java.net.URL
Resource
您可以配置部署到应用程序上下文中的 Bean 以实现特殊的
回调接口 ,将在
初始化时间,应用程序上下文本身作为 .
还可以公开 类型的属性,用于访问静态资源。
它们像任何其他属性一样被注入其中。您可以将这些属性指定为简单路径,并依赖于从这些文本进行自动转换
部署 Bean 时将字符串添加到实际对象。ResourceLoaderAware
ResourceLoader
Resource
Resource
String
Resource
提供给构造函数的一个或多个位置路径实际上是
资源字符串,并以简单的形式,根据特定的
上下文实现。例如,对待一个简单的
location path 作为类路径位置。还可以使用位置路径(资源字符串)
使用特殊前缀强制从类路径或 URL 加载定义,
与实际上下文类型无关。ApplicationContext
ClassPathXmlApplicationContext
应用程序启动跟踪
管理 Spring 应用程序的生命周期,并提供丰富的
围绕组件的编程模型。因此,复杂的应用程序可以同样具有
复杂的组件图和启动阶段。ApplicationContext
使用特定指标跟踪应用程序启动步骤有助于了解位置 在启动阶段花费了时间,但它也可以用作更好的一种方式 从整体上了解上下文生命周期。
(及其子类)使用 ,用于收集有关各个启动阶段的数据: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()
应用程序上下文已使用多个步骤进行检测。 一旦记录下来,就可以使用特定工具收集、显示和分析这些启动步骤。 有关现有启动步骤的完整列表,您可以查看专用的附录部分。
默认实现是无操作变体,以最小化开销。
这意味着默认情况下,在应用程序启动期间不会收集任何指标。
Spring Framework 附带了一个用于跟踪 Java Flight Recorder 启动步骤的实现:.要使用此变体,您必须配置它的实例
一旦它被创建。ApplicationStartup
FlightRecorderApplicationStartup
ApplicationContext
如果开发人员提供自己的子类,或者希望收集更精确的数据,也可以使用基础结构。ApplicationStartup
AbstractApplicationContext
ApplicationStartup 仅用于应用程序启动期间,用于
核心容器;这绝不是 Java 分析器或
指标库,如 Micrometer。 |
要开始收集自定义,组件可以直接从应用上下文中获取实例,让自己的组件实现,
或询问任何注射点的类型。StartupStep
ApplicationStartup
ApplicationStartupAware
ApplicationStartup
开发人员在创建自定义启动步骤时不应使用命名空间。
此命名空间保留供 Spring 内部使用,并且可能会更改。"spring.*" |
方便的 ApplicationWeb 应用程序的上下文实例化
例如,您可以使用 .当然,您也可以创建实例
通过使用其中一个实现以编程方式。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>
侦听器检查参数。如果参数没有
存在,侦听器用作默认值。当
参数确实存在,侦听器使用预定义的参数来分隔
分隔符(逗号、分号和空格),并使用这些值作为位置,其中
搜索应用程序上下文。还支持 Ant 样式的路径模式。
例如(对于名称以 结尾且驻留在目录中的所有文件)和 (对于 的任何子目录中的所有此类文件)。contextConfigLocation
/WEB-INF/applicationContext.xml
String
/WEB-INF/*Context.xml
Context.xml
WEB-INF
/WEB-INF/**/*Context.xml
WEB-INF
将 Spring 部署为 Jakarta EE RAR 文件ApplicationContext
可以将 Spring 部署为 RAR 文件,封装
上下文及其所有必需的 Bean 类和库 JAR 在 Jakarta EE RAR 部署中
单位。这相当于引导一个独立的(仅托管的
在 Jakarta EE 环境中)能够访问 Jakarta EE 服务器设施。RAR 部署
是部署无头 WAR 文件方案的更自然的替代方法——实际上,
没有任何 HTTP 入口点的 WAR 文件,仅用于在 Jakarta EE 环境中引导 Spring。ApplicationContext
ApplicationContext
ApplicationContext
RAR 部署非常适合不需要 HTTP 入口点但
而仅由消息端点和计划作业组成。在这种情况下,豆类可以
使用应用程序服务器资源,例如 JTA 事务管理器和 JNDI 绑定的 JDBC 实例和 JMS 实例,还可以注册
该平台的 JMX 服务器 — 全部通过 Spring 的标准事务管理和 JNDI
和 JMX 支持设施。应用程序组件还可以与应用程序交互
服务器的 JCA 通过 Spring 的抽象。DataSource
ConnectionFactory
WorkManager
TaskExecutor
有关RAR部署中涉及的配置详细信息,请参阅SpringContextResourceAdapter
类的javadoc。
要将 Spring ApplicationContext 部署为 Jakarta EE RAR 文件,请执行以下操作:
-
包 所有应用程序类都放入一个 RAR 文件(这是一个标准的 JAR 文件,具有不同的 文件扩展名)。
-
将所有必需的库 JAR 添加到 RAR 存档的根目录中。
-
添加部署描述符(如
SpringContextResourceAdapter
的 javadoc 中所示) 以及相应的 Spring XML Bean 定义文件(通常为 )。META-INF/ra.xml
META-INF/applicationContext.xml
-
将生成的 RAR 文件放入 应用程序服务器的部署目录。
这种RAR部署单元通常是独立的。它们不会公开组件
对外界,甚至对同一应用程序的其他模块也不行。与
基于 RAR 通常通过与其共享的 JMS 目标发生
其他模块。例如,基于 RAR 的还可以安排一些作业
或对文件系统中的新文件(或类似文件)做出反应。如果它需要允许同步
从外部访问,它可以(例如)导出 RMI 端点,这些端点可用于
由同一台机器上的其他应用程序模块提供。ApplicationContext ApplicationContext |