Customizing the Nature of a Bean
生命周期回调接口允许 bean 执行诸如在初始化和销毁时执行任务的操作。
有感知的接口使 bean 能够访问容器提供的服务,例如 ApplicationContext 和 BeanClassLoader。
有感知的接口包括:
-
ApplicationContextAware:提供对 ApplicationContext 的访问。
-
BeanNameAware:提供对 bean 名称的访问。
-
BeanClassLoaderAware:提供对类加载器的访问。
-
BeanFactoryAware:提供对 BeanFactory 的访问。
Spring Framework 提供了许多接口,可用于自定义 bean 的本质。此部分将其分组如下:
The Spring Framework provides a number of interfaces you can use to customize the nature of a bean. This section groups them as follows:
Lifecycle Callbacks
要与容器对 bean 生命周期进行管理进行交互,您可以实现 Spring InitializingBean
和 DisposableBean
接口。容器对前者调用 afterPropertiesSet()
,对后者调用 destroy()
,以便在 bean 初始化和销毁时让 bean 执行某些操作。
To interact with the container’s management of the bean lifecycle, you can implement
the Spring InitializingBean
and DisposableBean
interfaces. The container calls
afterPropertiesSet()
for the former and destroy()
for the latter to let the bean
perform certain actions upon initialization and destruction of your beans.
JSR-250 The JSR-250 如果您不想使用 JSR-250 注解,但仍希望解除耦合,请考虑使用 If you do not want to use the JSR-250 annotations but you still want to remove
coupling, consider |
Spring 框架在内部使用 BeanPostProcessor
实现来处理任何它能找到的回调接口并调用适当的方法。如果您需要 Spring 默认情况下不提供的自定义特性或其他生命周期行为,您可以自己实现 BeanPostProcessor
。有关更多信息,请参阅Container Extension Points。
Internally, the Spring Framework uses BeanPostProcessor
implementations to process any
callback interfaces it can find and call the appropriate methods. If you need custom
features or other lifecycle behavior Spring does not by default offer, you can
implement a BeanPostProcessor
yourself. For more information, see
Container Extension Points.
除了初始化和销毁回调以外,Spring 管理的对象还可以实现 Lifecycle
接口,以便这些对象可以参与启动和关闭进程,由容器自己的生命周期驱动。
In addition to the initialization and destruction callbacks, Spring-managed objects may
also implement the Lifecycle
interface so that those objects can participate in the
startup and shutdown process, as driven by the container’s own lifecycle.
生命周期回调接口在此部分中描述。
The lifecycle callback interfaces are described in this section.
Initialization Callbacks
org.springframework.beans.factory.InitializingBean
接口让 bean 在容器对 bean 设置所有必要属性之后执行初始化工作。InitializingBean
接口指定了一个方法:
The org.springframework.beans.factory.InitializingBean
interface lets a bean
perform initialization work after the container has set all necessary properties on the
bean. The InitializingBean
interface specifies a single method:
void afterPropertiesSet() throws Exception;
我们建议你不使用 InitializingBean
接口,因为它不必要地将代码耦合到 Spring。或者,我们建议使用 @PostConstruct
注释或指定一个 POJO 初始化方法。对于基于 XML 的配置元数据,你可以使用 init-method
属性来指定具有 void 无参数签名的那个方法的名称。对于 Java 配置,你可以使用 @Bean
的 initMethod
属性。参见 Receiving Lifecycle Callbacks。考虑以下示例:
We recommend that you do not use the InitializingBean
interface, because it
unnecessarily couples the code to Spring. Alternatively, we suggest using
the @PostConstruct
annotation or
specifying a POJO initialization method. In the case of XML-based configuration metadata,
you can use the init-method
attribute to specify the name of the method that has a void
no-argument signature. With Java configuration, you can use the initMethod
attribute of
@Bean
. See Receiving Lifecycle Callbacks. Consider the following example:
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
-
Java
-
Kotlin
public class ExampleBean {
public void init() {
// do some initialization work
}
}
class ExampleBean {
fun init() {
// do some initialization work
}
}
前一个示例的效果几乎与以下示例(由两个表列组成)完全相同:
The preceding example has almost exactly the same effect as the following example (which consists of two listings):
<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
-
Java
-
Kotlin
public class AnotherExampleBean implements InitializingBean {
@Override
public void afterPropertiesSet() {
// do some initialization work
}
}
class AnotherExampleBean : InitializingBean {
override fun afterPropertiesSet() {
// do some initialization work
}
}
但是,这两个前一个示例中的第一个示例不会将代码与 Spring 耦合在一起。
However, the first of the two preceding examples does not couple the code to Spring.
请注意, Be aware that 对于要触发昂贵的后初始化活动(例如,异步数据库准备步骤)的方案,您的 bean 应当实现 For a scenario where expensive post-initialization activity is to be triggered,
e.g. asynchronous database preparation steps, your bean should either implement
或者,您也可以实现 Alternatively, you may implement the |
Destruction Callbacks
实现 org.springframework.beans.factory.DisposableBean
接口使得 bean 能够在包含它的容器被销毁时获取回调。DisposableBean
接口指定了一个方法:
Implementing the org.springframework.beans.factory.DisposableBean
interface lets a
bean get a callback when the container that contains it is destroyed. The
DisposableBean
interface specifies a single method:
void destroy() throws Exception;
我们建议你不使用 DisposableBean
回调接口,因为它不必要地将代码耦合到 Spring。或者,我们建议使用 @PreDestroy
注释或指定一个由 bean 定义支持的通用方法。对于基于 XML 的配置元数据,你可以对 <bean/>
中的 destroy-method
属性使用。对于 Java 配置,你可以使用 @Bean
的 destroyMethod
属性。参见 Receiving Lifecycle Callbacks。考虑以下定义:
We recommend that you do not use the DisposableBean
callback interface, because it
unnecessarily couples the code to Spring. Alternatively, we suggest using
the @PreDestroy
annotation or
specifying a generic method that is supported by bean definitions. With XML-based
configuration metadata, you can use the destroy-method
attribute on the <bean/>
.
With Java configuration, you can use the destroyMethod
attribute of @Bean
. See
Receiving Lifecycle Callbacks. Consider the following definition:
<bean id="exampleDestructionBean" class="examples.ExampleBean" destroy-method="cleanup"/>
-
Java
-
Kotlin
public class ExampleBean {
public void cleanup() {
// do some destruction work (like releasing pooled connections)
}
}
class ExampleBean {
fun cleanup() {
// do some destruction work (like releasing pooled connections)
}
}
上一个定义几乎与以下定义具有相同的效果:
The preceding definition has almost exactly the same effect as the following definition:
<bean id="exampleDestructionBean" class="examples.AnotherExampleBean"/>
-
Java
-
Kotlin
public class AnotherExampleBean implements DisposableBean {
@Override
public void destroy() {
// do some destruction work (like releasing pooled connections)
}
}
class AnotherExampleBean : DisposableBean {
override fun destroy() {
// do some destruction work (like releasing pooled connections)
}
}
但是,两个之前的定义中的第一个定义并没有将代码与 Spring 耦合。
However, the first of the two preceding definitions does not couple the code to Spring.
请注意,Spring 还支持销毁方法的推断,检测公开的 close
或 shutdown
方法。这是 Java 配置类中的 @Bean
方法的默认行为,并且自动匹配 java.lang.AutoCloseable
或 java.io.Closeable
实现,也不会将销毁逻辑与 Spring 耦合。
Note that Spring also supports inference of destroy methods, detecting a public close
or
shutdown
method. This is the default behavior for @Bean
methods in Java configuration
classes and automatically matches java.lang.AutoCloseable
or java.io.Closeable
implementations, not coupling the destruction logic to Spring either.
对于带有 XML 的销毁方法推断,您可以将 |
For destroy method inference with XML, you may assign the |
对于扩展的关闭阶段,您可以实现 For extended shutdown phases, you may implement the |
Default Initialization and Destroy Methods
当您编写不使用 Spring 特定的 InitializingBean
和 DisposableBean
回调接口的初始化和销毁方法回调时,通常会编写一些名称为 init()
、initialize()
、dispose()
等等的方法。理想情况下,这种生命周期回调方法的名称在整个项目中都是标准化的,以便所有开发人员都使用相同的方法名称,并确保一致性。
When you write initialization and destroy method callbacks that do not use the
Spring-specific InitializingBean
and DisposableBean
callback interfaces, you
typically write methods with names such as init()
, initialize()
, dispose()
,
and so on. Ideally, the names of such lifecycle callback methods are standardized across
a project so that all developers use the same method names and ensure consistency.
你可以配置 Spring 容器以 “look” 初始化和销毁方法名称上的每个 Bean。这意味着你作为应用程序开发人员,可以编写你的应用程序类并使用调用为 init()
的初始化回调方法,而无需使用每个 Bean 定义配置 init-method="init"
属性。当创建 Bean 时(并按照标准生命周期回调约定 described previously),Spring IoC 容器将调用该方法。此功能还强制执行初始化和销毁方法回调的一致命名约定。
You can configure the Spring container to “look” for named initialization and destroy
callback method names on every bean. This means that you, as an application developer,
can write your application classes and use an initialization callback called init()
,
without having to configure an init-method="init"
attribute with each bean definition.
The Spring IoC container calls that method when the bean is created (and in accordance
with the standard lifecycle callback contract described previously).
This feature also enforces a consistent naming convention for initialization and
destroy method callbacks.
假设您的初始化回调方法名为 init()
,并且您的销毁回调方法名为 destroy()
。那么,您的类将类似于以下示例中的类:
Suppose that your initialization callback methods are named init()
and your destroy
callback methods are named destroy()
. Your class then resembles the class in the
following example:
-
Java
-
Kotlin
public class DefaultBlogService implements BlogService {
private BlogDao blogDao;
public void setBlogDao(BlogDao blogDao) {
this.blogDao = blogDao;
}
// this is (unsurprisingly) the initialization callback method
public void init() {
if (this.blogDao == null) {
throw new IllegalStateException("The [blogDao] property must be set.");
}
}
}
class DefaultBlogService : BlogService {
private var blogDao: BlogDao? = null
// this is (unsurprisingly) the initialization callback method
fun init() {
if (blogDao == null) {
throw IllegalStateException("The [blogDao] property must be set.")
}
}
}
然后,您可以在类似于以下内容的 bean 中使用该类:
You could then use that class in a bean resembling the following:
<beans default-init-method="init">
<bean id="blogService" class="com.something.DefaultBlogService">
<property name="blogDao" ref="blogDao" />
</bean>
</beans>
顶级 <beans/>
元素属性上的 default-init-method
属性的存在导致 Spring IoC 容器识别 bean 类上的一个名为 init
的方法作为初始化方法回调。当创建一个 bean 并将其组装起来时,如果 bean 类具有此类方法,则它将在适当的时候被调用。
The presence of the default-init-method
attribute on the top-level <beans/>
element
attribute causes the Spring IoC container to recognize a method called init
on the bean
class as the initialization method callback. When a bean is created and assembled, if the
bean class has such a method, it is invoked at the appropriate time.
您可以通过使用顶级 <beans/>
元素上的 default-destroy-method
属性,以类似的方式(即在 XML 中)配置销毁方法回调。
You can configure destroy method callbacks similarly (in XML, that is) by using the
default-destroy-method
attribute on the top-level <beans/>
element.
在现有的 bean 类已拥有与约定不相符的命名回调方法的情况下,您可以通过(即在 XML 中)使用 <bean/>
本身的 init-method
和 destroy-method
属性指定方法名称,从而覆盖默认值。
Where existing bean classes already have callback methods that are named at variance
with the convention, you can override the default by specifying (in XML, that is) the
method name by using the init-method
and destroy-method
attributes of the <bean/>
itself.
Spring 容器保证,在为 bean 提供所有依赖项之后,立即调用配置的初始化回调。因此,初始化回调是在原始 bean 引用上调用的,这意味着尚未将 AOP 拦截器等应用到 bean 上。首先创建目标 bean,然后应用 AOP 代理(例如)及其拦截器链。如果目标 bean 和代理分开定义,则您的代码甚至可以与原始目标 bean 进行交互,从而绕过代理。因此,将拦截器应用于 init
方法是不一致的,因为这样做会将目标 bean 的生命周期与其代理或拦截器耦合,并且当您的代码直接与原始目标 bean 进行交互时,会留下奇怪的语义。
The Spring container guarantees that a configured initialization callback is called
immediately after a bean is supplied with all dependencies. Thus, the initialization
callback is called on the raw bean reference, which means that AOP interceptors and so
forth are not yet applied to the bean. A target bean is fully created first and
then an AOP proxy (for example) with its interceptor chain is applied. If the target
bean and the proxy are defined separately, your code can even interact with the raw
target bean, bypassing the proxy. Hence, it would be inconsistent to apply the
interceptors to the init
method, because doing so would couple the lifecycle of the
target bean to its proxy or interceptors and leave strange semantics when your code
interacts directly with the raw target bean.
Combining Lifecycle Mechanisms
从 Spring 2.5 开始,您有三个选项用于控制 bean 生命周期行为:
As of Spring 2.5, you have three options for controlling bean lifecycle behavior:
-
The
InitializingBean
andDisposableBean
callback interfaces -
Custom
init()
anddestroy()
methods -
The
@PostConstruct
and@PreDestroy
annotations[style="arabic"]-
You can combine these mechanisms to control a given bean.
-
如果为 bean 配置了多个生命周期机制,并且每个机制都配置了不同的方法名称,那么每个已配置的方法都将在此注释后面列出的顺序中运行。但是,如果为多个此类生命周期机制配置了相同的方法名称 - 例如,某个初始化方法的 |
If multiple lifecycle mechanisms are configured for a bean and each mechanism is
configured with a different method name, then each configured method is run in the
order listed after this note. However, if the same method name is configured — for example,
|
为同一 bean 配置了多个生命周期机制,具有不同的初始化方法,它们将按如下方式调用:
Multiple lifecycle mechanisms configured for the same bean, with different initialization methods, are called as follows:
-
Methods annotated with
@PostConstruct
-
afterPropertiesSet()
as defined by theInitializingBean
callback interface -
A custom configured
init()
method
销毁方法按相同顺序调用:
Destroy methods are called in the same order:
-
Methods annotated with
@PreDestroy
-
destroy()
as defined by theDisposableBean
callback interface -
A custom configured
destroy()
method
Startup and Shutdown Callbacks
Lifecycle
接口定义了任何对自己的生命周期要求(例如启动和停止某些后台进程)的对象必备的方法:
The Lifecycle
interface defines the essential methods for any object that has its own
lifecycle requirements (such as starting and stopping some background process):
public interface Lifecycle {
void start();
void stop();
boolean isRunning();
}
任何 Spring 管理的对象都可以实现 Lifecycle
接口。然后,当 ApplicationContext
本身接收启动和停止信号(例如,在运行时进行停止/重新启动方案)时,它会将这些调用级联到该上下文内定义的所有 Lifecycle
实现。它通过委托给以下清单中显示的 LifecycleProcessor
来完成此操作:
Any Spring-managed object may implement the Lifecycle
interface. Then, when the
ApplicationContext
itself receives start and stop signals (for example, for a stop/restart
scenario at runtime), it cascades those calls to all Lifecycle
implementations
defined within that context. It does this by delegating to a LifecycleProcessor
, shown
in the following listing:
public interface LifecycleProcessor extends Lifecycle {
void onRefresh();
void onClose();
}
请注意,LifecycleProcessor
本身是 Lifecycle
接口的扩展。它还增加了另外两种方法来响应上下文被刷新和关闭。
Notice that the LifecycleProcessor
is itself an extension of the Lifecycle
interface. It also adds two other methods for reacting to the context being refreshed
and closed.
请注意,常规 Note that the regular 另外,请注意,不能保证停止通知在销毁之前到来。在常规关闭时,所有 Also, please note that stop notifications are not guaranteed to come before destruction.
On regular shutdown, all |
启动和关闭调用的顺序非常重要。如果在两个对象之间存在“depends-on
”关系,则从属方在其依赖项之后启动,并在其依赖项之前停止。然而,有时直接依赖关系是未知的。您可能只知道某种类型的对象应该在另一种类型的对象之前启动。在这些情况下,SmartLifecycle
接口定义了另一个选项,即在其超接口 Phased
上定义的 getPhase()
方法。以下清单显示了 Phased
接口的定义:
The order of startup and shutdown invocations can be important. If a “depends-on”
relationship exists between any two objects, the dependent side starts after its
dependency, and it stops before its dependency. However, at times, the direct
dependencies are unknown. You may only know that objects of a certain type should start
prior to objects of another type. In those cases, the SmartLifecycle
interface defines
another option, namely the getPhase()
method as defined on its super-interface,
Phased
. The following listing shows the definition of the Phased
interface:
public interface Phased {
int getPhase();
}
以下清单显示了 SmartLifecycle
接口的定义:
The following listing shows the definition of the SmartLifecycle
interface:
public interface SmartLifecycle extends Lifecycle, Phased {
boolean isAutoStartup();
void stop(Runnable callback);
}
启动时,阶段最低的对象先启动。在停止时,按照倒序进行。因此,实现 SmartLifecycle
且其 getPhase()
方法返回 Integer.MIN_VALUE
的对象将是最先启动和最后停止的对象。另一方面,一个 phase 值为 Integer.MAX_VALUE
表示对象应该最后启动并首先停止(可能是因为它依赖于其他正在运行的进程)。考虑 phase 值时,还必须知道未实现 SmartLifecycle
的任何“normal
”Lifecycle
对象的默认 phase 为 0
。因此,任何负 phase 值都表示一个对象应该在这些标准组件之前启动(并在它们之后停止)。任何正 phase 值都是相反的。
When starting, the objects with the lowest phase start first. When stopping, the
reverse order is followed. Therefore, an object that implements SmartLifecycle
and
whose getPhase()
method returns Integer.MIN_VALUE
would be among the first to start
and the last to stop. At the other end of the spectrum, a phase value of
Integer.MAX_VALUE
would indicate that the object should be started last and stopped
first (likely because it depends on other processes to be running). When considering the
phase value, it is also important to know that the default phase for any “normal”
Lifecycle
object that does not implement SmartLifecycle
is 0
. Therefore, any
negative phase value indicates that an object should start before those standard
components (and stop after them). The reverse is true for any positive phase value.
SmartLifecycle
定义的 stop 方法接受一个回调。在该实现的关闭进程完成后,任何实现都必须调用该回调的 run()
方法。由于 LifecycleProcessor
接口的默认实现 DefaultLifecycleProcessor
会为每个 phase 中的对象组等待其超时值以调用该回调,因此这可以在必要时启用异步关闭。每个阶段的默认超时时间为 30 秒。你可以通过在上下文中定义名为 lifecycleProcessor
的 Bean 来重写默认的生命周期处理器实例。如果你只想修改超时,定义以下内容就足够了:
The stop method defined by SmartLifecycle
accepts a callback. Any
implementation must invoke that callback’s run()
method after that implementation’s
shutdown process is complete. That enables asynchronous shutdown where necessary, since
the default implementation of the LifecycleProcessor
interface,
DefaultLifecycleProcessor
, waits up to its timeout value for the group of objects
within each phase to invoke that callback. The default per-phase timeout is 30 seconds.
You can override the default lifecycle processor instance by defining a bean named
lifecycleProcessor
within the context. If you want only to modify the timeout,
defining the following would suffice:
<bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor">
<!-- timeout value in milliseconds -->
<property name="timeoutPerShutdownPhase" value="10000"/>
</bean>
如前所述,LifecycleProcessor
接口还为上下文的刷新和关闭定义了回调方法。后者驱动停止进程,就像明确调用了 stop()
一样,但它发生在上下文关闭时。另一方面,“refresh”回调启用 SmartLifecycle
Bean 的另一个功能。刷新上下文时(在所有对象已被实例化和初始化之后),将调用该回调。在这一点上,默认的生命周期处理器将检查每个 SmartLifecycle
对象的 isAutoStartup()
方法返回的布尔值。如果为 true
,则该对象将在那时启动,而不是等待明确调用上下文的或其自己的 start()
方法(与上下文刷新不同,上下文启动不会自动发生在标准上下文实现中)。如前所述,phase
值和任何“depends-on
”关系确定启动顺序。
As mentioned earlier, the LifecycleProcessor
interface defines callback methods for the
refreshing and closing of the context as well. The latter drives the shutdown
process as if stop()
had been called explicitly, but it happens when the context is
closing. The 'refresh' callback, on the other hand, enables another feature of
SmartLifecycle
beans. When the context is refreshed (after all objects have been
instantiated and initialized), that callback is invoked. At that point, the
default lifecycle processor checks the boolean value returned by each
SmartLifecycle
object’s isAutoStartup()
method. If true
, that object is
started at that point rather than waiting for an explicit invocation of the context’s or
its own start()
method (unlike the context refresh, the context start does not happen
automatically for a standard context implementation). The phase
value and any
“depends-on” relationships determine the startup order as described earlier.
Shutting Down the Spring IoC Container Gracefully in Non-Web Applications
此部分仅适用于非 Web 应用程序。Spring 的基于 Web 的 This section applies only to non-web applications. Spring’s web-based
|
如果你在非 Web 应用程序环境(例如,在富客户端桌面环境)中使用 Spring 的 IoC 容器,请使用 JVM 注册一个关闭挂钩。这样做可以确保优雅地关闭并调用单例 Bean 上的相关销毁方法,以便释放所有资源。你仍然必须正确配置和实现这些销毁回调。
If you use Spring’s IoC container in a non-web application environment (for example, in a rich client desktop environment), register a shutdown hook with the JVM. Doing so ensures a graceful shutdown and calls the relevant destroy methods on your singleton beans so that all resources are released. You must still configure and implement these destroy callbacks correctly.
要注册一个关闭挂钩,请调用 ConfigurableApplicationContext
接口上声明的 registerShutdownHook()
方法,如下例所示:
To register a shutdown hook, call the registerShutdownHook()
method that is
declared on the ConfigurableApplicationContext
interface, as the following example shows:
-
Java
-
Kotlin
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public final class Boot {
public static void main(final String[] args) throws Exception {
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
// add a shutdown hook for the above context...
ctx.registerShutdownHook();
// app runs here...
// main method exits, hook is called prior to the app shutting down...
}
}
import org.springframework.context.support.ClassPathXmlApplicationContext
fun main() {
val ctx = ClassPathXmlApplicationContext("beans.xml")
// add a shutdown hook for the above context...
ctx.registerShutdownHook()
// app runs here...
// main method exits, hook is called prior to the app shutting down...
}
Thread Safety and Visibility
Spring 核心容器以线程安全的方式发布创建的单例实例,通过单例锁保护访问权限,并保证在其他线程中可见。
The Spring core container publishes created singleton instances in a thread-safe manner, guarding access through a singleton lock and guaranteeing visibility in other threads.
因此,应用程序提供的 Bean 类不必担心其初始化状态的可见性。只要它们只在初始化阶段发生变化,常规配置字段不必标记为 volatile
,即使对于在该初始阶段可变的基于 setter 的配置状态,它也提供了类似于 final
的可见性保证。如果在 Bean 创建阶段及其后续初始发布之后更改了这些字段,则在访问时需要将它们声明为 volatile
或受公共锁保护。
As a consequence, application-provided bean classes do not have to be concerned about the
visibility of their initialization state. Regular configuration fields do not have to be
marked as volatile
as long as they are only mutated during the initialization phase,
providing visibility guarantees similar to final
even for setter-based configuration
state that is mutable during that initial phase. If such fields get changed after the
bean creation phase and its subsequent initial publication, they need to be declared as
volatile
or guarded by a common lock whenever accessed.
请注意,在从容器方面安全地进行初始发布之后,并发访问单例 Bean 实例中的此类配置状态(例如,对于控制器实例或存储库实例)是完全线程安全的。这包括通用单例 FactoryBean
实例,它们也在通用单例锁内进行处理。
Note that concurrent access to such configuration state in singleton bean instances,
e.g. for controller instances or repository instances, is perfectly thread-safe after
such safe initial publication from the container side. This includes common singleton
FactoryBean
instances which are processed within the general singleton lock as well.
对于销毁回调,配置状态仍然是线程安全的,但根据通用 Java 指南,初始化和销毁之间累积的任何运行时状态都应保留在线程安全结构中(或在简单情况下保留在 volatile
字段中)。
For destruction callbacks, the configuration state remains thread-safe but any runtime
state accumulated between initialization and destruction should be kept in thread-safe
structures (or in volatile
fields for simple cases) as per common Java guidelines.
如上所示,更深入的 Lifecycle
集成涉及运行时可变状态,例如必须声明为 volatile
的 runnable
字段。虽然公共生命周期回调遵循特定顺序(例如,保证只有在完全初始化后才发生启动回调,并且只有在初始启动后才发生停止回调),但有一个特殊情况是销毁之前的常用停止安排:强烈建议这种情况下的任何 Bean 中的内部状态也允许立即销毁回调,而无需先停止,因为这可能会在取消引导后或在由另一个 Bean 导致的停止超时的情况下发生的非正常关闭期间发生。
Deeper Lifecycle
integration as shown above involves runtime-mutable state such as
a runnable
field which will have to be declared as volatile
. While the common
lifecycle callbacks follow a certain order, e.g. a start callback is guaranteed to
only happen after full initialization and a stop callback only after an initial start,
there is a special case with the common stop before destroy arrangement: It is strongly
recommended that the internal state in any such bean also allows for an immediate
destroy callback without a preceding stop since this may happen during an extraordinary
shutdown after a cancelled bootstrap or in case of a stop timeout caused by another bean.
ApplicationContextAware
and BeanNameAware
当 ApplicationContext
创建实现 org.springframework.context.ApplicationContextAware
接口的对象实例时,会向该 ApplicationContext
提供对该实例的引用。以下清单显示了 ApplicationContextAware
接口的定义:
When an ApplicationContext
creates an object instance that implements the
org.springframework.context.ApplicationContextAware
interface, the instance is provided
with a reference to that ApplicationContext
. The following listing shows the definition
of the ApplicationContextAware
interface:
public interface ApplicationContextAware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
因此,bean 可以通过 ApplicationContext
接口或通过将引用强制转换为该接口的已知子类的实例(例如公开附加功能的 ConfigurableApplicationContext
)以编程方式操作创建它们的 ApplicationContext
。一个用例是通过编程方式检索其他 bean。有时该功能非常有用。但是,通常情况下,您应该避免使用它,因为它将代码与 Spring 耦合,并且不遵循控制反转风格,而此风格会将合作者作为属性提供给 bean。ApplicationContext
的其他方法提供对文件资源、发布应用程序事件以及访问 MessageSource
的访问权限。这些附加特性在Additional Capabilities of the ApplicationContext
中进行了说明。
Thus, beans can programmatically manipulate the ApplicationContext
that created them,
through the ApplicationContext
interface or by casting the reference to a known
subclass of this interface (such as ConfigurableApplicationContext
, which exposes
additional functionality). One use would be the programmatic retrieval of other beans.
Sometimes this capability is useful. However, in general, you should avoid it, because
it couples the code to Spring and does not follow the Inversion of Control style,
where collaborators are provided to beans as properties. Other methods of the
ApplicationContext
provide access to file resources, publishing application events,
and accessing a MessageSource
. These additional features are described in
Additional Capabilities of the ApplicationContext
.
自动装配是获得对`ApplicationContext`的引用方法的另一种替代方法。traditional constructor
和 byType`自动装配模式(如 Autowiring Collaborators 中描述)可以为构造函数参数或 setter 方法参数提供类型为`ApplicationContext`的依赖项。对于包括自动装配字段和多参数方法的功能在内的更多灵活性,请使用基于注释的自动装配特性。如果您这样做,如果相关字段、构造函数或方法带有 `@Autowired
注释,则无论 ApplicationContext
是否自动装配到字段、构造函数参数或方法参数,都期望 ApplicationContext
类型。有关更多信息,请参阅 Using @Autowired
。
Autowiring is another alternative to obtain a reference to the
ApplicationContext
. The traditional constructor
and byType
autowiring modes
(as described in Autowiring Collaborators) can provide a dependency of type
ApplicationContext
for a constructor argument or a setter method parameter,
respectively. For more flexibility, including the ability to autowire fields and
multiple parameter methods, use the annotation-based autowiring features. If you do,
the ApplicationContext
is autowired into a field, constructor argument, or method
parameter that expects the ApplicationContext
type if the field, constructor, or
method in question carries the @Autowired
annotation. For more information, see
Using @Autowired
.
当 ApplicationContext
创建实现 org.springframework.beans.factory.BeanNameAware
接口的类时,会向该类提供对其在关联对象定义中定义的名称的引用。以下清单显示 BeanNameAware 接口的定义:
When an ApplicationContext
creates a class that implements the
org.springframework.beans.factory.BeanNameAware
interface, the class is provided with
a reference to the name defined in its associated object definition. The following listing
shows the definition of the BeanNameAware interface:
public interface BeanNameAware {
void setBeanName(String name) throws BeansException;
}
回调在设置常规 bean 属性后但在初始化回调(例如 InitializingBean.afterPropertiesSet()
或自定义初始化方法)之前调用。
The callback is invoked after population of normal bean properties but before an
initialization callback such as InitializingBean.afterPropertiesSet()
or a custom
init-method.
Other Aware
Interfaces
除了 ApplicationContextAware
和 BeanNameAware
(见 earlier),Spring 提供了广泛的 Aware
回调接口,这些接口允许 Bean 指示容器它们需要特定的基础架构依赖性。作为一般规则,名称表示依赖类型。下表总结了最重要的 Aware
接口:
Besides ApplicationContextAware
and BeanNameAware
(discussed earlier),
Spring offers a wide range of Aware
callback interfaces that let beans indicate to the container
that they require a certain infrastructure dependency. As a general rule, the name indicates the
dependency type. The following table summarizes the most important Aware
interfaces:
Name | Injected Dependency | Explained in… |
---|---|---|
|
Declaring |
|
|
Event publisher of the enclosing |
|
|
Class loader used to load the bean classes. |
|
|
Declaring |
|
|
Name of the declaring bean. |
|
|
Defined weaver for processing class definition at load time. |
|
|
Configured strategy for resolving messages (with support for parameterization and internationalization). |
|
|
Spring JMX notification publisher. |
|
|
Configured loader for low-level access to resources. |
|
|
Current |
|
|
Current |
请再次注意,使用这些接口会将您的代码绑定到 Spring API,且不遵循控制反转风格。因此,我们建议将它们用于需要对容器进行编程访问的基础架构 bean。
Note again that using these interfaces ties your code to the Spring API and does not follow the Inversion of Control style. As a result, we recommend them for infrastructure beans that require programmatic access to the container.