对于最新稳定版本,请使用Spring Framework 7.0.1spring-doc.cadn.net.cn

附加功能应用上下文

正如章节引言中讨论的,org.springframework.beans.factory包为管理和作豆子提供了基本功能,包括在 程序化的方式。这org.springframework.contextpackage 会添加应用上下文接口,扩展了豆子工厂除了扩展其他接口外 接口,以在更广泛的应用中提供额外功能 以框架为导向的风格。许多人使用应用上下文完全在 声明式的表达方式,甚至不是通过程序创建,而是依赖于 支援类如上下文加载器以自动实例化应用上下文作为雅加达电子工程网页应用正常启动流程的一部分。spring-doc.cadn.net.cn

为了增强豆子工厂功能以更框架导向的风格,上下文 包还提供以下功能:spring-doc.cadn.net.cn

国际化消息源

应用上下文接口扩展了一个称为消息源和 因此,提供了国际化(“i18N”)功能。Spring还能提供分层消息源接口,可以分层解析消息。 这些界面共同构成了春季效果信息的基础 分辨率。这些接口定义的方法包括:spring-doc.cadn.net.cn

  • 字符串 getMessage(字符串代码,Object[] args,字符串默认,Locale loc):基本 用于从以下地区获取消息的方法消息源.当找不到任何消息时 对于指定的地点,使用默认消息。任何通过的论点都变成 替换值,使用消息格式标准提供的功能 图书馆。spring-doc.cadn.net.cn

  • String getMessage(String code, Object[] args, Locale loc):本质上是一样的 与之前的方法不同,但有一个不同:不能指定默认消息。如果 找不到消息,aNoSuchMessageException被抛出。spring-doc.cadn.net.cn

  • String getMessage(MessageSourceResolvable resolvable, Locale locale):所有属性 前述方法中的 也被包裹在一个名为消息来源可解决你可以用这个方法来使用。spring-doc.cadn.net.cn

应用上下文加载时,它会自动搜索消息源在语境中定义了“豆”。豆子必须有名字消息来源.如果这样一个豆子 找到后,所有对前述方法的调用都委托给消息源。如果没有 消息源被找到,则应用上下文试图找到包含 同名的豆子。如果有,它会用那颗豆子作为消息源.如果应用上下文找不到任何消息来源,空的委派消息源实例化后能够接受对 上述方法。spring-doc.cadn.net.cn

Spring带来了三条消息源实现资源包消息源,ReloadableResourceBundleMessageSource静态消息源.所有这些分层消息源为了实现嵌套 消息。这静态消息源很少使用,但提供了程序化的方式 向源头添加信息。以下示例显示资源包消息源:spring-doc.cadn.net.cn

<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标准的方式处理消息,通过以下方式资源包对象。对于 示例的目的是,假设上述两个资源捆绑文件的内容 具体如下:spring-doc.cadn.net.cn

# in format.properties
message=Alligators rock!
# in exceptions.properties
argument.required=The {0} argument is required.

下一个示例展示了一个程序来运行消息源功能性。 记住这些应用上下文实现也包括消息源实现和 可以转换为消息源接口。spring-doc.cadn.net.cn

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

上述程序的结果如下:spring-doc.cadn.net.cn

Alligators rock!

总结一下,消息源定义在一个名为beans.xml哪 存在于你类路径的根源。这消息来源豆子的定义指的是 通过其资源捆集的数量基号财产。这三个文件是 在名单中传递给基号属性存在于你的根节点文件中 类路径和称为format.properties,exceptions.propertieswindows.properties分别。spring-doc.cadn.net.cn

下一个示例展示了传递给消息查找的参数。这些论点是 改装为字符串对象并插入查找消息中的占位符。spring-doc.cadn.net.cn

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

调用 后产生的输出执行()方法如下:spring-doc.cadn.net.cn

The userDao argument is required.

关于国际化(“i18n”),春季的各种情况消息源实现遵循与标准JDK相同的局部分辨率和备用规则资源包.简而言之,继续举例消息来源定义 之前,如果你想解决针对英国的消息 (en-GB)地点,你 会生成名为format_en_GB.properties,exceptions_en_GB.propertieswindows_en_GB.properties分别。spring-doc.cadn.net.cn

通常,地点分辨率由 应用。在以下例子中,英国消息所针对的地区是 解析由手动指定:spring-doc.cadn.net.cn

# in exceptions_en_GB.properties
argument.required=Ebagum lad, the ''{0}'' argument is required, I say, required.
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)
}

运行上述程序的结果如下:spring-doc.cadn.net.cn

Ebagum lad, the 'userDao' argument is required, I say, required.

你也可以使用消息来源接口以获取对任意的引用消息源这已经被定义了。任何定义在应用上下文实现了消息来源接口注入 应用上下文消息源当豆子被创造和配置时。spring-doc.cadn.net.cn

因为Spring消息源基于 Java 的资源包,它不会合并 与基底名称相同的捆绑包,但只使用第一个找到的捆绑包。 后续带有相同基名的消息包则被忽略。
作为替代方案资源包消息源,Spring提供了ReloadableResourceBundleMessageSource类。该变体支持相同的捆绑包 文件格式,但比基于标准的JDK更灵活资源包消息源实现。特别是,它允许阅读 来自任意 Spring 资源位置的文件(不仅仅是类路径)并支持 Hot 重新加载bundle属性文件(同时高效缓存)。 参见ReloadableResourceBundleMessageSource详情请用Javadoc。

标准赛事与定制赛事

事件处理在应用上下文通过ApplicationEvent类和ApplicationListener接口。如果一个实现ApplicationListener接口部署到上下文中,每次ApplicationEvent发布到......应用上下文,那个豆子被通知了。 本质上,这就是Observer的标准设计模式。spring-doc.cadn.net.cn

截至春季4.2,活动基础设施得到了显著提升,并提供了 基于注释的模型以及 能够发布任意事件(即一个不一定 从ApplicationEvent).当这样的对象被发布时,我们会将其包裹在 为你举办的活动。

下表描述了春季赛事的标准赛事:spring-doc.cadn.net.cn

表1。内置活动
事件 解释

ContextRefreshedEventspring-doc.cadn.net.cn

发表时间应用上下文初始化或刷新(例如,由 使用refresh()方法ConfigurableApplicationContext界面)。 这里的“初始化”意味着所有豆子都已加载,后处理器豆子被检测到 激活时,单元素元被预实例化,且应用上下文对象是 准备使用。只要上下文未关闭,就可以触发刷新 多次,前提是被选中者应用上下文实际上支持这样的 “热”的refresh。例如XmlWeb应用上下文支持热刷新,但通用应用上下文不。spring-doc.cadn.net.cn

ContextStartedEventspring-doc.cadn.net.cn

发表时间应用上下文通过使用开始()方法ConfigurableApplicationContext接口。这里,“开始”意味着所有生命周期豆子会收到明确的启动信号。通常,这个信号用于重新启动豆子 在显式停止之后,但它也可以用于启动尚未被停止的组件 配置为自动启动(例如,尚未启动的组件 初始化)。spring-doc.cadn.net.cn

ContextStoppedEventspring-doc.cadn.net.cn

发表时间应用上下文通过使用以下方式来阻止停止()方法ConfigurableApplicationContext接口。这里,“停止”意味着所有生命周期豆子会收到明确的停止信号。停止上下文可以通过开始()叫。spring-doc.cadn.net.cn

ContextClosedEventspring-doc.cadn.net.cn

发表时间应用上下文通过使用接近()方法 在ConfigurableApplicationContext接口或通过JVM关闭钩子。这里 “封闭”意味着所有单粒豆都会被销毁。一旦上下文关闭, 它已达到生命终点,无法刷新或重启。spring-doc.cadn.net.cn

请求处理事件spring-doc.cadn.net.cn

一个网络特定的事件,告诉所有 Beans HTTP 请求已被处理。这 请求完成后,事件才会发布。本事件仅适用于 使用 Spring 的网页应用调度器服务.spring-doc.cadn.net.cn

ServletRequestHandledEventspring-doc.cadn.net.cn

的一个子类请求处理事件这增加了 Servlet 特有的上下文信息。spring-doc.cadn.net.cn

你也可以创建并发布自己的自定义活动。以下示例展示了一个 扩展 Spring 的简单类ApplicationEvent基础职业:spring-doc.cadn.net.cn

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()方法应用事件发布者.通常,这通过创建一个实现应用程序、事件、出版者并登记为春季豆。如下 示例展示了这样一个类:spring-doc.cadn.net.cn

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 容器检测到电子邮件服务实现应用程序、事件、出版者并自动调用setApplicationEventPublisher().实际上,传入的参数是Spring 容器本身。你通过应用上下文与其交互应用事件发布者接口。spring-doc.cadn.net.cn

接受这个习俗ApplicationEvent,你可以创建一个实现ApplicationListener并注册为春季豆。以下示例 显示了这样的类:spring-doc.cadn.net.cn

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()方法阻塞,直到所有监听者都处理完事件。 这种同步单线程方法的一个优点是,当监听者接收到事件时, 如果有交易上下文可用,它会在发布者的交易上下文中运行。 如果需要其他事件发布策略,例如默认的异步事件处理, Spring的相关内容请参见javadocApplicationEventMulticaster接口 和SimpleApplicationEventMulticaster实现 用于配置选项,这些选项可以应用于自定义的“applicationEventMulticaster”豆定义。 在这种情况下,ThreadLocals 和日志上下文不会被传播用于事件处理。 看@EventListener可观测性部分关于可观测性问题的更多信息。spring-doc.cadn.net.cn

以下示例展示了用于注册和配置每个 的豆定义 上述课程:spring-doc.cadn.net.cn

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

把所有事情汇聚在一起,当发送邮件()方法电子邮件服务豆子是 如果有任何邮件应该被屏蔽,就会调用一个自定义事件BlockedListEvent已出版。这blockedListNotifierBean注册为ApplicationListener并且BlockedListEvent,此时它可以 通知相关人员。spring-doc.cadn.net.cn

Spring的事件机制设计用于Spring豆之间的简单通信 在同一应用环境中。然而,对于更复杂的企业来说, 独立维护的 Spring Integration 项目满足了集成需求 完全支持构建轻量化、模式导向、事件驱动 这些架构基于著名的Spring编程模型。

基于注释的事件监听器

你可以在管理豆的任何方法上注册事件监听器,方法是使用@EventListener注解。这BlockedListNotifier可以重写如下:spring-doc.cadn.net.cn

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...
	}
}

方法签名再次声明它监听的事件类型, 但这次采用了灵活的名称,且未实现特定的监听器接口。 事件类型也可以通过通用词缩小范围,只要是实际事件类型 在实现层级中解析你的通用参数。spring-doc.cadn.net.cn

你的方法应该听多个事件,还是想定义它,不 事件类型也可以在注释本身上指定。这 以下示例展示了如何实现:spring-doc.cadn.net.cn

@EventListener({ContextStartedEvent.class, ContextRefreshedEvent.class})
public void handleContextStart() {
	// ...
}
@EventListener(ContextStartedEvent::class, ContextRefreshedEvent::class)
fun handleContextStart() {
	// ...
}

也可以通过使用条件属性 定义 a 的注释SpEL表达,应当匹配 实际上是在某个特定事件中调用该方法。spring-doc.cadn.net.cn

以下示例展示了我们的通知符如何被重写为只有在内容事件属性等于我的事件:spring-doc.cadn.net.cn

@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表达是在专门的情境下评估的。下表列出了 提供给上下文以便你用于条件事件处理的项:spring-doc.cadn.net.cn

表2。SpEL表达式中的事件元数据
名称 位置 描述 示例

事件spring-doc.cadn.net.cn

根对象spring-doc.cadn.net.cn

实际ApplicationEvent.spring-doc.cadn.net.cn

#root.事件事件spring-doc.cadn.net.cn

参数数组spring-doc.cadn.net.cn

根对象spring-doc.cadn.net.cn

调用方法时使用的参数(作为对象数组)。spring-doc.cadn.net.cn

#root.argsargs; args[0]以获取第一个论点等。spring-doc.cadn.net.cn

论元名称spring-doc.cadn.net.cn

评估背景spring-doc.cadn.net.cn

某个特定方法论元的名称。如果名字不可得 (例如,因为代码编译时没有-参数旗帜),个人 参数也可用#a<#arg>语法 其中<#arg>代表 论元索引(从0开始)。spring-doc.cadn.net.cn

#blEvent#a0(你也可以使用#p0#p<#arg>参数符号作为别名)spring-doc.cadn.net.cn

注意#root.事件即使你的方法,也能访问底层事件 签名实际上指的是被发布的任意对象。spring-doc.cadn.net.cn

如果你需要发布一个事件,是处理另一个事件的结果,你可以更改 方法签名以返回应发布的事件,如下示例所示:spring-doc.cadn.net.cn

@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()方法发布了新的列表更新事件对于每个BlockedListEvent它能处理。如果你需要发布多个活动,可以回来 一个收集或者说是一系列事件。spring-doc.cadn.net.cn

异步监听器

如果你希望某个特定的监听器异步处理事件,可以重复使用以下条件定期@Async支持. 以下示例展示了如何实现:spring-doc.cadn.net.cn

@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
}

使用异步事件时请注意以下限制:spring-doc.cadn.net.cn

排序听众

如果你需要先调用一个监听者,可以添加@Order方法声明的注释,如下示例所示:spring-doc.cadn.net.cn

@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是实际被创造的实体类型。比如你 可以创建以下监听者定义,仅接收实体创建事件对于:spring-doc.cadn.net.cn

@EventListener
public void onPersonCreated(EntityCreatedEvent<Person> event) {
	// ...
}
@EventListener
fun onPersonCreated(event: EntityCreatedEvent<Person>) {
	// ...
}

由于类型擦除,只有当触发的事件能解决泛型时,这才有效 事件监听器过滤的参数(即类似class PersonCreatedEvent 扩展了 EntityCreatedEvent<Person> { ... }).spring-doc.cadn.net.cn

在某些情况下,如果所有事件都相同,这可能会变得相当繁琐 结构(如前述事件应有的结构)。在这种情况下, 你可以实现ResolvableTypeProvider引导框架超越运行时范围 环境提供。以下活动展示了如何实现:spring-doc.cadn.net.cn

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 定义替换或自定义, 例如,用于异步处理所有事件和/或处理监听器异常:spring-doc.cadn.net.cn

@Bean
ApplicationEventMulticaster applicationEventMulticaster() {
	SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
	multicaster.setTaskExecutor(...);
	multicaster.setErrorHandler(...);
	return multicaster;
}

便捷访问低层资源

为了最大化使用和理解应用上下文,你应该熟悉 你和Spring的资源抽象,详见资源spring-doc.cadn.net.cn

应用上下文是ResourceLoader,可以用来加载资源对象。 一个资源本质上是JDK的更丰富的功能版本java.net.URL类。 事实上,以下实现资源包裹一个实例java.net.URL哪里 适当。一个资源几乎可以从 透明的方式,包括来自类路径(classpath,文件系统位置)的任意地点 可用标准网址描述,以及其他一些变体。如果资源位置 字符串是一条没有特殊前缀的简单路径,这些资源的来源为 具体且适合实际应用上下文类型。spring-doc.cadn.net.cn

你可以配置部署到应用上下文中的豆来实现特殊 回调接口,ResourceLoaderAware,将自动回拨于 初始化时间与应用上下文本身传递为ResourceLoader. 你也可以暴露 类型的属性资源用于访问静态资源。 它们像其他属性一样被注入其中。你可以具体说明这些资源性质为简单字符串路径并依赖于从这些文本自动转换 字符串到实际资源当豆子被部署时,对象。spring-doc.cadn.net.cn

提供给应用上下文构造者实际上是 资源字符串,简单形式根据具体情况适当处理 上下文实现。例如ClassPathXmlApplicationContext处理 简单 位置路径作为类路径位置。你也可以使用位置路径(资源字符串) 并带有特殊前缀,强制从类路径或URL加载定义, 无论实际的语境类型如何。spring-doc.cadn.net.cn

应用启动跟踪

应用上下文管理 Spring 应用的生命周期,并提供丰富的 围绕组件进行编程模型。因此,复杂的应用可以同样具有 复杂的组件图和启动阶段。spring-doc.cadn.net.cn

通过具体指标跟踪应用启动步骤,有助于了解具体位置 在创业阶段,时间被消耗,但也可以作为改进的手段 了解上下文生命周期的整体。spring-doc.cadn.net.cn

摘要应用上下文(及其子类)通过ApplicationStartup,该集合创业步关于各个创业阶段的数据:spring-doc.cadn.net.cn

这里有一个仪器化的示例AnnotationConfigApplicationContext:spring-doc.cadn.net.cn

// 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-doc.cadn.net.cn

默认ApplicationStartup实现方式为无作变体,开销最小。 这意味着默认情况下,应用启动时不会收集任何指标。 Spring Framework 自带了一个用于跟踪 Java 飞行记录器启动步骤的实现:飞行记录应用启动.要使用该变体,必须配置其实例 前往应用上下文一旦它被创建。spring-doc.cadn.net.cn

开发者还可以使用ApplicationStartup如果他们自己提供基础设施,那就要有摘要应用上下文子类,或者如果他们想收集更精确的数据。spring-doc.cadn.net.cn

ApplicationStartup仅用于应用启动时及核心容器;这绝不是 Java 分析器或像 Micrometer 这样的度量库的替代品。

开始收集自定义创业步,分量可以得到ApplicationStartup直接从应用上下文中实例,让他们的组件实现应用启动感知, 或者要求ApplicationStartup在任意注射点输入。spring-doc.cadn.net.cn

开发者不应使用“Spring。”创建自定义启动步骤时的命名空间。该命名空间保留给 Spring 内部使用,可能会发生变化。

便捷的 ApplicationContext 实现 Web 应用

你可以创造应用上下文通过声明式地使用实例,例如:上下文加载器. 当然,你也可以创作应用上下文实例 通过使用其中一种应用上下文实现。spring-doc.cadn.net.cn

你可以注册一个应用上下文通过使用ContextLoaderListener,如以下示例显示:spring-doc.cadn.net.cn

<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参数。 如果参数不存在,监听者使用/网-INF/applicationContext.xml作为默认。当参数确实存在时,监听者会分离字符串通过使用预定义的分隔符(逗号、分号和空白符)并使用这些值作为位置应用上下文的搜索。也支持Ant式路径模式。示例包括/网-INF/*Context.xml(对于所有名称以Context.xml网内目录)和/网-INF/**/*Context.xml(对于任意子目录中的所有此类文件网内).spring-doc.cadn.net.cn

Spring的展开应用上下文作为雅加达EE RAR文件

可以部署Spring应用上下文作为一个 RAR 文件,封装了上下文及其所有在雅加达 EE RAR 部署中所需的 bean 类和库 JAR 单位。 这相当于自力更生一个独立软件应用上下文(仅托管雅加达EE环境)能够访问雅加达EE服务器设施。RAR部署是部署无头WAR文件的更自然替代方案——实际上,一个没有HTTP入口的WAR文件,仅用于启动Spring应用上下文在雅加达电气工程环境中。spring-doc.cadn.net.cn

RAR部署非常适合不需要HTTP入口点的应用上下文,仅由消息端点和调度作业组成。在这样的环境中,豆子可以使用应用服务器资源,如JTA事务管理器和绑定JNDI的JDBC数据来源实例与JMS连接工厂实例和也可以注册到平台的 JMX 服务器——所有这些都通过 Spring 的标准事务管理和 JNDI以及 JMX 支持设施。应用组件也可以与应用交互服务器的 JCA工作经理通过斯普林斯任务执行者抽象化。spring-doc.cadn.net.cn

参见 javadocSpringContextResourceAdapter用于RAR部署中涉及的配置细节。spring-doc.cadn.net.cn

对于将 Spring ApplicationContext 作为雅加达 EE RAR 文件进行简单部署:spring-doc.cadn.net.cn

  1. 包 所有应用类都集成到一个RAR文件(这是一个标准的JAR文件,扩展名不同文件扩展名)。spring-doc.cadn.net.cn

  2. 将所有必要的库 JAR 添加到 RAR 归档的根节点中。spring-doc.cadn.net.cn

  3. 添加一个元步兵/ra.xml部署描述符(如Java doc forSpringContextResourceAdapter) 以及对应的Spring XML bean定义文件(通常为元基础applicationContext.xml).spring-doc.cadn.net.cn

  4. 将生成的 RAR 文件丢入你的应用服务器的部署目录。spring-doc.cadn.net.cn

此类RAR部署单元通常是自包含的。它们不会将组件暴露给外部世界,甚至不会暴露给同一应用的其他模块。与基于RAR的交互应用上下文通常通过与其他模块共享的 JMS 目的地发生。基于 RAR 的应用上下文例如,还可以调度一些作业或对文件系统中的新文件做出反应(或类似文件)。如果需要允许同步的外部访问,它可以(例如)导出 RMI 端点,这些端点可以被同一台机器上的其他应用模块使用