Additional Capabilities of the ApplicationContext
1.15. Additional Capabilities of the ApplicationContext
As discussed in the chapter introduction, the org.springframework.beans.factory
package provides basic functionality for managing and manipulating beans, including in a programmatic way. The org.springframework.context
package adds the ApplicationContext
interface, which extends the BeanFactory
interface, in addition to extending other interfaces to provide additional functionality in a more application framework-oriented style. Many people use the ApplicationContext
in a completely declarative fashion, not even creating it programmatically, but instead relying on support classes such as ContextLoader
to automatically instantiate an ApplicationContext
as part of the normal startup process of a Java EE web application.
To enhance BeanFactory
functionality in a more framework-oriented style, the context package also provides the following functionality:
- Access to messages in i18n-style, through the
MessageSource
interface. - Access to resources, such as URLs and files, through the
ResourceLoader
interface. - Event publication, namely to beans that implement the
ApplicationListener
interface, through the use of theApplicationEventPublisher
interface. - Loading of multiple (hierarchical) contexts, letting each be focused on one particular layer, such as the web layer of an application, through the
HierarchicalBeanFactory
interface.
- 通过MessageSource接口访问i18n风格的消息。
- 通过ResourceLoader接口访问资源,例如url和文件。
- 事件发布,即通过使用ApplicationEventPublisher接口发布到实现ApplicationListener接口的bean。
- 加载多个(分层的)上下文,通过HierarchicalBeanFactory接口将每个上下文集中在一个特定的层上,例如应用程序的web层。
1.15.1. Internationalization using `MessageSource`
The ApplicationContext
interface extends an interface called MessageSource
and, therefore, provides internationalization (“i18n”) functionality. Spring also provides the HierarchicalMessageSource
interface, which can resolve messages hierarchically. Together, these interfaces provide the foundation upon which Spring effects message resolution. The methods defined on these interfaces include:
String getMessage(String code, Object[] args, String default, Locale loc)
: The basic method used to retrieve a message from theMessageSource
. When no message is found for the specified locale, the default message is used. Any arguments passed in become replacement values, using theMessageFormat
functionality provided by the standard library.String getMessage(String code, Object[] args, Locale loc)
: Essentially the same as the previous method but with one difference: No default message can be specified. If the message cannot be found, aNoSuchMessageException
is thrown.String getMessage(MessageSourceResolvable resolvable, Locale locale)
: All properties used in the preceding methods are also wrapped in a class namedMessageSourceResolvable
, which you can use with this method.
- String getMessage(String code, Object[] args, String default, Locale loc):用于从MessageSource检索消息的基本方法。如果没有找到针对指定地区的消息,则使用默认消息。通过使用标准库提供的MessageFormat功能,传入的任何参数都将成为替换值。
- String getMessage(String code, Object[] args, Locale loc):本质上与前面的方法相同,但有一点不同:不能指定缺省消息。如果无法找到该消息,则抛出NoSuchMessageException。
- String getMessage(MessageSourceResolvable可解析的,Locale Locale):前面方法中使用的所有属性也被包装在一个名为MessageSourceResolvable的类中,您可以在此方法中使用该类。
When an ApplicationContext
is loaded, it automatically searches for a MessageSource
bean defined in the context. The bean must have the name messageSource
. If such a bean is found, all calls to the preceding methods are delegated to the message source. If no message source is found, the ApplicationContext
attempts to find a parent containing a bean with the same name. If it does, it uses that bean as the MessageSource
. If the ApplicationContext
cannot find any source for messages, an empty DelegatingMessageSource
is instantiated in order to be able to accept calls to the methods defined above.
Spring provides three MessageSource
implementations, ResourceBundleMessageSource
, ReloadableResourceBundleMessageSource
and StaticMessageSource
. All of them implement HierarchicalMessageSource
in order to do nested messaging. The StaticMessageSource
is rarely used but provides programmatic ways to add messages to the source. The following example shows 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>
The example assumes that you have three resource bundles called format
, exceptions
and windows
defined in your classpath. Any request to resolve a message is handled in the JDK-standard way of resolving messages through ResourceBundle
objects. For the purposes of the example, assume the contents of two of the above resource bundle files are as follows:
# in format.properties
message=Alligators rock!
# in exceptions.properties
argument.required=The {0} argument is required.
The next example shows a program to run the MessageSource
functionality. Remember that all ApplicationContext
implementations are also MessageSource
implementations and so can be cast to the MessageSource
interface.
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);
}
The resulting output from the above program is as follows:
Alligators rock!
To summarize, the MessageSource
is defined in a file called beans.xml
, which exists at the root of your classpath. The messageSource
bean definition refers to a number of resource bundles through its basenames
property. The three files that are passed in the list to the basenames
property exist as files at the root of your classpath and are called format.properties
, exceptions.properties
, and windows.properties
, respectively.
The next example shows arguments passed to the message lookup. These arguments are converted into String
objects and inserted into placeholders in the lookup message.
<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);
}
}
The resulting output from the invocation of the execute()
method is as follows:
The userDao argument is required.
With regard to internationalization (“i18n”), Spring’s various MessageSource
implementations follow the same locale resolution and fallback rules as the standard JDK ResourceBundle
. In short, and continuing with the example messageSource
defined previously, if you want to resolve messages against the British (en-GB
) locale, you would create files called format_en_GB.properties
, exceptions_en_GB.properties
, and windows_en_GB.properties
, respectively.
Typically, locale resolution is managed by the surrounding environment of the application. In the following example, the locale against which (British) messages are resolved is specified manually:
# 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);
}
The resulting output from the running of the above program is as follows:
Ebagum lad, the 'userDao' argument is required, I say, required.
You can also use the MessageSourceAware
interface to acquire a reference to any MessageSource
that has been defined. Any bean that is defined in an ApplicationContext
that implements the MessageSourceAware
interface is injected with the application context’s MessageSource
when the bean is created and configured.
Because Spring’s
MessageSource
is based on Java’sResourceBundle
, it does not merge bundles with the same base name, but will only use the first bundle found. Subsequent message bundles with the same base name are ignored.
As an alternative to
ResourceBundleMessageSource
, Spring provides aReloadableResourceBundleMessageSource
class. This variant supports the same bundle file format but is more flexible than the standard JDK basedResourceBundleMessageSource
implementation. In particular, it allows for reading files from any Spring resource location (not only from the classpath) and supports hot reloading of bundle property files (while efficiently caching them in between). See theReloadableResourceBundleMessageSource
javadoc for details.
1.15.2. Standard and Custom Events
Event handling in the ApplicationContext
is provided through the ApplicationEvent
class and the ApplicationListener
interface. If a bean that implements the ApplicationListener
interface is deployed into the context, every time an ApplicationEvent
gets published to the ApplicationContext
, that bean is notified. Essentially, this is the standard Observer design pattern.
As of Spring 4.2, the event infrastructure has been significantly improved and offers an annotation-based model as well as the ability to publish any arbitrary event (that is, an object that does not necessarily extend from
ApplicationEvent
). When such an object is published, we wrap it in an event for you.
The following table describes the standard events that Spring provides:
Event | Explanation | 说明 |
---|---|---|
ContextRefreshedEvent |
Published when the ApplicationContext is initialized or refreshed (for example, by using the refresh() method on the ConfigurableApplicationContext interface). Here, “initialized” means that all beans are loaded, post-processor beans are detected and activated, singletons are pre-instantiated, and the ApplicationContext object is ready for use. As long as the context has not been closed, a refresh can be triggered multiple times, provided that the chosen ApplicationContext actually supports such “hot” refreshes. For example, XmlWebApplicationContext supports hot refreshes, but GenericApplicationContext does not. |
当ApplicationContext初始化或刷新时发布(例如,通过使用ConfigurableApplicationContext接口上的refresh()方法)。在这里,“初始化”意味着加载所有bean,检测和激活后处理器bean,预实例化单例,并准备使用ApplicationContext对象。只要上下文没有关闭,刷新就可以被触发多次,只要所选的ApplicationContext实际上支持这种“热”刷新。例如,XmlWebApplicationContext支持热刷新,但GenericApplicationContext不支持。 |
ContextStartedEvent |
Published when the ApplicationContext is started by using the start() method on the ConfigurableApplicationContext interface. Here, “started” means that all Lifecycle beans receive an explicit start signal. Typically, this signal is used to restart beans after an explicit stop, but it may also be used to start components that have not been configured for autostart (for example, components that have not already started on initialization). |
在使用ConfigurableApplicationContext接口上的start()方法启动ApplicationContext时发布。在这里,“started”意味着所有生命周期bean都接收一个显式的开始信号。通常,此信号用于显式停止后重新启动bean,但它也可以用于启动未配置为自动启动的组件(例如,在初始化时尚未启动的组件)。 |
ContextStoppedEvent |
Published when the ApplicationContext is stopped by using the stop() method on the ConfigurableApplicationContext interface. Here, “stopped” means that all Lifecycle beans receive an explicit stop signal. A stopped context may be restarted through a start() call. |
在使用ConfigurableApplicationContext接口上的stop()方法停止ApplicationContext时发布。在这里,“停止”意味着所有生命周期bean都接收到一个显式的停止信号。一个已停止的上下文可以通过start()调用重新启动。 |
ContextClosedEvent |
Published when the ApplicationContext is being closed by using the close() method on the ConfigurableApplicationContext interface or via a JVM shutdown hook. Here, "closed" means that all singleton beans will be destroyed. Once the context is closed, it reaches its end of life and cannot be refreshed or restarted. |
通过在ConfigurableApplicationContext接口上使用close()方法或通过JVM关闭钩子关闭ApplicationContext时发布。在这里,“关闭”意味着将销毁所有单例bean。一旦上下文被关闭,它就会到达生命的尽头,无法刷新或重新启动。 |
RequestHandledEvent |
A web-specific event telling all beans that an HTTP request has been serviced. This event is published after the request is complete. This event is only applicable to web applications that use Spring’s DispatcherServlet . |
一个特定于web的事件,告诉所有bean一个HTTP请求已经得到服务。此事件在请求完成后发布。此事件仅适用于使用Spring的DispatcherServlet的web应用程序。 |
ServletRequestHandledEvent |
A subclass of RequestHandledEvent that adds Servlet-specific context information. |
RequestHandledEvent的子类,用于添加特定于servlet的上下文信息。 |
You can also create and publish your own custom events. The following example shows a simple class that extends Spring’s ApplicationEvent
base class:
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...
}
To publish a custom ApplicationEvent
, call the publishEvent()
method on an ApplicationEventPublisher
. Typically, this is done by creating a class that implements ApplicationEventPublisherAware
and registering it as a Spring bean. The following example shows such a class:
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...
}
}
At configuration time, the Spring container detects that EmailService
implements ApplicationEventPublisherAware
and automatically calls setApplicationEventPublisher()
. In reality, the parameter passed in is the Spring container itself. You are interacting with the application context through its ApplicationEventPublisher
interface.
To receive the custom ApplicationEvent
, you can create a class that implements ApplicationListener
and register it as a Spring bean. The following example shows such a class:
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...
}
}
Notice that ApplicationListener
is generically parameterized with the type of your custom event (BlockedListEvent
in the preceding example). This means that the onApplicationEvent()
method can remain type-safe, avoiding any need for downcasting. You can register as many event listeners as you wish, but note that, by default, event listeners receive events synchronously. This means that the publishEvent()
method blocks until all listeners have finished processing the event. One advantage of this synchronous and single-threaded approach is that, when a listener receives an event, it operates inside the transaction context of the publisher if a transaction context is available. If another strategy for event publication becomes necessary, see the javadoc for Spring’s ApplicationEventMulticaster
interface and SimpleApplicationEventMulticaster
implementation for configuration options.
The following example shows the bean definitions used to register and configure each of the classes above:
<bean id="emailService" class="example.EmailService">
<property name="blockedList">
<list>
<value>known.spammer@example.org</value>
<value>known.hacker@example.org</value>
<value>john.doe@example.org</value>
</list>
</property>
</bean>
<bean id="blockedListNotifier" class="example.BlockedListNotifier">
<property name="notificationAddress" value="blockedlist@example.org"/>
</bean>
Putting it all together, when the sendEmail()
method of the emailService
bean is called, if there are any email messages that should be blocked, a custom event of type BlockedListEvent
is published. The blockedListNotifier
bean is registered as an ApplicationListener
and receives the BlockedListEvent
, at which point it can notify appropriate parties.
Spring’s eventing mechanism is designed for simple communication between Spring beans within the same application context. However, for more sophisticated enterprise integration needs, the separately maintained Spring Integration project provides complete support for building lightweight, pattern-oriented, event-driven architectures that build upon the well-known Spring programming model.
Annotation-based Event Listeners
You can register an event listener on any method of a managed bean by using the @EventListener
annotation. The BlockedListNotifier
can be rewritten as follows:
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...
}
}
The method signature once again declares the event type to which it listens, but, this time, with a flexible name and without implementing a specific listener interface. The event type can also be narrowed through generics as long as the actual event type resolves your generic parameter in its implementation hierarchy.
If your method should listen to several events or if you want to define it with no parameter at all, the event types can also be specified on the annotation itself. The following example shows how to do so:
@EventListener({ContextStartedEvent.class, ContextRefreshedEvent.class})
public void handleContextStart() {
// ...
}
It is also possible to add additional runtime filtering by using the condition
attribute of the annotation that defines a SpEL
expression, which should match to actually invoke the method for a particular event.
The following example shows how our notifier can be rewritten to be invoked only if the content
attribute of the event is equal to my-event
:
@EventListener(condition = "#blEvent.content == 'my-event'")
public void processBlockedListEvent(BlockedListEvent blEvent) {
// notify appropriate parties via notificationAddress...
}
Each SpEL
expression evaluates against a dedicated context. The following table lists the items made available to the context so that you can use them for conditional event processing:
Name | Location | Description | Example |
---|---|---|---|
Event | root object | The actual ApplicationEvent . |
#root.event or event |
Arguments array | root object | The arguments (as an object array) used to invoke the method. | #root.args or args ; args[0] to access the first argument, etc. |
Argument name | evaluation context | The name of any of the method arguments. If, for some reason, the names are not available (for example, because there is no debug information in the compiled byte code), individual arguments are also available using the #a<#arg> syntax where <#arg> stands for the argument index (starting from 0). |
#blEvent or #a0 (you can also use #p0 or #p<#arg> parameter notation as an alias) |
Note that #root.event
gives you access to the underlying event, even if your method signature actually refers to an arbitrary object that was published.
If you need to publish an event as the result of processing another event, you can change the method signature to return the event that should be published, as the following example shows:
@EventListener
public ListUpdateEvent handleBlockedListEvent(BlockedListEvent event) {
// notify appropriate parties via notificationAddress and
// then publish a ListUpdateEvent...
}
This feature is not supported for asynchronous listeners.
The handleBlockedListEvent()
method publishes a new ListUpdateEvent
for every BlockedListEvent
that it handles. If you need to publish several events, you can return a Collection
or an array of events instead.
Asynchronous Listeners
If you want a particular listener to process events asynchronously, you can reuse the regular @Async
support. The following example shows how to do so:
@EventListener
@Async
public void processBlockedListEvent(BlockedListEvent event) {
// BlockedListEvent is processed in a separate thread
}
Be aware of the following limitations when using asynchronous events:
- If an asynchronous event listener throws an
Exception
, it is not propagated to the caller. SeeAsyncUncaughtExceptionHandler
for more details. - Asynchronous event listener methods cannot publish a subsequent event by returning a value. If you need to publish another event as the result of the processing, inject an
ApplicationEventPublisher
to publish the event manually.
- 如果异步事件监听器抛出异常,则不会将其传播给调用者。更多细节请参见AsyncUncaughtExceptionHandler。
- 异步事件监听器方法不能通过返回值来发布后续事件。如果您需要作为处理的结果发布另一个事件,请注入一个ApplicationEventPublisher来手动发布事件。
Ordering Listeners
If you need one listener to be invoked before another one, you can add the @Order
annotation to the method declaration, as the following example shows:
@EventListener
@Order(42)
public void processBlockedListEvent(BlockedListEvent event) {
// notify appropriate parties via notificationAddress...
}
Generic Events
You can also use generics to further define the structure of your event. Consider using an EntityCreatedEvent<T>
where T
is the type of the actual entity that got created. For example, you can create the following listener definition to receive only EntityCreatedEvent
for a Person
:
@EventListener
public void onPersonCreated(EntityCreatedEvent<Person> event) {
// ...
}
Due to type erasure, this works only if the event that is fired resolves the generic parameters on which the event listener filters (that is, something like class PersonCreatedEvent extends EntityCreatedEvent<Person> { … }
).
class PersonCreatedEvent extends EntityCreatedEvent<Person> { … }
)时,这种方法才有效。
In certain circumstances, this may become quite tedious if all events follow the same structure (as should be the case for the event in the preceding example). In such a case, you can implement ResolvableTypeProvider
to guide the framework beyond what the runtime environment provides. The following event shows how to do so:
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()));
}
}
This works not only for
ApplicationEvent
but any arbitrary object that you send as an event.
1.15.3. Convenient Access to Low-level Resources
For optimal usage and understanding of application contexts, you should familiarize yourself with Spring’s Resource
abstraction, as described in Resources.
An application context is a ResourceLoader
, which can be used to load Resource
objects. A Resource
is essentially a more feature rich version of the JDK java.net.URL
class. In fact, the implementations of the Resource
wrap an instance of java.net.URL
, where appropriate. A Resource
can obtain low-level resources from almost any location in a transparent fashion, including from the classpath, a filesystem location, anywhere describable with a standard URL, and some other variations. If the resource location string is a simple path without any special prefixes, where those resources come from is specific and appropriate to the actual application context type.
You can configure a bean deployed into the application context to implement the special callback interface, ResourceLoaderAware
, to be automatically called back at initialization time with the application context itself passed in as the ResourceLoader
. You can also expose properties of type Resource
, to be used to access static resources. They are injected into it like any other properties. You can specify those Resource
properties as simple String
paths and rely on automatic conversion from those text strings to actual Resource
objects when the bean is deployed.
The location path or paths supplied to an ApplicationContext
constructor are actually resource strings and, in simple form, are treated appropriately according to the specific context implementation. For example ClassPathXmlApplicationContext
treats a simple location path as a classpath location. You can also use location paths (resource strings) with special prefixes to force loading of definitions from the classpath or a URL, regardless of the actual context type.
1.15.4. Application Startup Tracking
The ApplicationContext
manages the lifecycle of Spring applications and provides a rich programming model around components. As a result, complex applications can have equally complex component graphs and startup phases.
Tracking the application startup steps with specific metrics can help understand where time is being spent during the startup phase, but it can also be used as a way to better understand the context lifecycle as a whole.
The AbstractApplicationContext
(and its subclasses) is instrumented with an ApplicationStartup
, which collects StartupStep
data about various startup phases:
- application context lifecycle (base packages scanning, config classes management)
- beans lifecycle (instantiation, smart initialization, post processing)
- application events processing
- 应用程序上下文生命周期(基本包扫描、配置类管理)
- bean生命周期(实例化、智能初始化、后处理)
- 应用程序事件处理
Here is an example of instrumentation in the AnnotationConfigApplicationContext
:
// create a startup step and start recording
StartupStep scanPackages = this.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();
The application context is already instrumented with multiple steps. Once recorded, these startup steps can be collected, displayed and analyzed with specific tools. For a complete list of existing startup steps, you can check out the dedicated appendix section.
The default ApplicationStartup
implementation is a no-op variant, for minimal overhead. This means no metrics will be collected during application startup by default. Spring Framework ships with an implementation for tracking startup steps with Java Flight Recorder: FlightRecorderApplicationStartup
. To use this variant, you must configure an instance of it to the ApplicationContext
as soon as it’s been created.
Developers can also use the ApplicationStartup
infrastructure if they’re providing their own AbstractApplicationContext
subclass, or if they wish to collect more precise data.
ApplicationStartup
is meant to be only used during application startup and for the core container; this is by no means a replacement for Java profilers or metrics libraries like Micrometer.
To start collecting custom StartupStep
, components can either get the ApplicationStartup
instance from the application context directly, make their component implement ApplicationStartupAware
, or ask for the ApplicationStartup
type on any injection point.
Developers should not use the
"spring.*"
namespace when creating custom startup steps. This namespace is reserved for internal Spring usage and is subject to change.
1.15.5. Convenient ApplicationContext Instantiation for Web Applications
You can create ApplicationContext
instances declaratively by using, for example, a ContextLoader
. Of course, you can also create ApplicationContext
instances programmatically by using one of the ApplicationContext
implementations.
You can register an ApplicationContext
by using the ContextLoaderListener
, as the following example shows:
<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>
The listener inspects the contextConfigLocation
parameter. If the parameter does not exist, the listener uses /WEB-INF/applicationContext.xml
as a default. When the parameter does exist, the listener separates the String
by using predefined delimiters (comma, semicolon, and whitespace) and uses the values as locations where application contexts are searched. Ant-style path patterns are supported as well. Examples are /WEB-INF/*Context.xml
(for all files with names that end with Context.xml
and that reside in the WEB-INF
directory) and /WEB-INF/**/*Context.xml
(for all such files in any subdirectory of WEB-INF
).
1.15.6. Deploying a Spring `ApplicationContext` as a Java EE RAR File
It is possible to deploy a Spring ApplicationContext
as a RAR file, encapsulating the context and all of its required bean classes and library JARs in a Java EE RAR deployment unit. This is the equivalent of bootstrapping a stand-alone ApplicationContext
(only hosted in Java EE environment) being able to access the Java EE servers facilities. RAR deployment is a more natural alternative to a scenario of deploying a headless WAR file — in effect, a WAR file without any HTTP entry points that is used only for bootstrapping a Spring ApplicationContext
in a Java EE environment.
RAR deployment is ideal for application contexts that do not need HTTP entry points but rather consist only of message endpoints and scheduled jobs. Beans in such a context can use application server resources such as the JTA transaction manager and JNDI-bound JDBC DataSource
instances and JMS ConnectionFactory
instances and can also register with the platform’s JMX server — all through Spring’s standard transaction management and JNDI and JMX support facilities. Application components can also interact with the application server’s JCA WorkManager
through Spring’s TaskExecutor
abstraction.
See the javadoc of the SpringContextResourceAdapter
class for the configuration details involved in RAR deployment.
For a simple deployment of a Spring ApplicationContext as a Java EE RAR file:
- Package all application classes into a RAR file (which is a standard JAR file with a different file extension).
- Add all required library JARs into the root of the RAR archive.
- Add a
META-INF/ra.xml
deployment descriptor (as shown in the javadoc forSpringContextResourceAdapter
) and the corresponding Spring XML bean definition file(s) (typicallyMETA-INF/applicationContext.xml
). - Drop the resulting RAR file into your application server’s deployment directory.
- 将所有应用程序类打包到一个RAR文件中(RAR文件是一个具有不同文件扩展名的标准JAR文件)。
- 将所有必需的库jar添加到RAR归档文件的根中。
- 添加一个META-INF/ra.xml部署描述符(如用于SpringContextResourceAdapter的javadoc所示)和相应的Spring XML bean定义文件(通常是META-INF/applicationContext.xml)。
- 将生成的RAR文件放到应用程序服务器的部署目录中。
Such RAR deployment units are usually self-contained. They do not expose components to the outside world, not even to other modules of the same application. Interaction with a RAR-based
ApplicationContext
usually occurs through JMS destinations that it shares with other modules. A RAR-basedApplicationContext
may also, for example, schedule some jobs or react to new files in the file system (or the like). If it needs to allow synchronous access from the outside, it could (for example) export RMI endpoints, which may be used by other application modules on the same machine.