文章作者:Tyan
博客:noahsnail.com ?|? CSDN ?|? 簡(jiǎn)書(shū)
3.6 Customizing the nature of a bean
3.6.1 Lifecycle callbacks
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 allow the bean to perform certain actions upon initialization and destruction of your beans.
為了與容器中bean生命周期的管理進(jìn)行交互,你可以實(shí)現(xiàn)Spring的InitializingBean
和DisposableBean
接口。當(dāng)初始化beans時(shí)容器會(huì)調(diào)用InitializingBean
中的afterPropertiesSet()
方法,當(dāng)銷(xiāo)毀beans時(shí)容器會(huì)調(diào)用DisposableBean
中的destroy()
方法,在這兩個(gè)方法中bean可以執(zhí)行特定的行為。
The JSR-250
@PostConstruct
and@PreDestroy
annotations are generally considered best practice for receiving lifecycle callbacks in a modern Spring application. Using these annotations means that your beans are not coupled to Spring specific interfaces. For details see Section 3.9.8, “@PostConstruct and @PreDestroy”.
If you don’t want to use the JSR-250 annotations but you are still looking to remove coupling consider the use of init-method and destroy-method object definition metadata.
在現(xiàn)代Spring應(yīng)用中,通常認(rèn)為JSR-250的
@PostConstruct
和@PreDestroy
注解是最佳實(shí)踐接收生命周期回調(diào)函數(shù)的方法。使用這些注解意味著你的bean沒(méi)有耦合Spring特定的接口。更多細(xì)節(jié)請(qǐng)看3.9.8小節(jié),"@PostConstruct和@PreDestroy"。
如果你不想使用JSR-250注解,但你仍要注意解耦,可以考慮使用對(duì)象定義元數(shù)據(jù)中的初始化方法和方法。
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 offer out-of-the-box, you can implement a BeanPostProcessor
yourself. For more information, see Section 3.8, “Container Extension Points”.
在Spring內(nèi)部,Spring框架使用BeanPostProcessor
實(shí)現(xiàn)來(lái)處理任何它能發(fā)現(xiàn)的回調(diào)接口并調(diào)用合適的方法。如果你需要定制Spring不能提供的開(kāi)箱即用的功能或其它生命周期行為,你可以自己實(shí)現(xiàn)BeanPostProcessor
。更多信息請(qǐng)看3.8小節(jié),"容器擴(kuò)展點(diǎn)"。
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.
除了初始化回調(diào)函數(shù)和析構(gòu)回調(diào)函數(shù)之外,Spring管理的對(duì)象也可以實(shí)現(xiàn)Lifecycle
接口,這些對(duì)象可以參與容器自身生命周期驅(qū)動(dòng)的啟動(dòng)和關(guān)閉過(guò)程。
The lifecycle callback interfaces are described in this section.
本節(jié)描述了生命周期回調(diào)接口。
Initialization callbacks
The org.springframework.beans.factory.InitializingBean
interface allows a bean to perform initialization work after all necessary properties on the bean have been set by the container. The InitializingBean
interface specifies a single method:
org.springframework.beans.factory.InitializingBean
接口在容器設(shè)置了bean所有的必須屬性之后,允許bean執(zhí)行初始化工作。InitializingBean
接口指定了一個(gè)方法:
void afterPropertiesSet() throws Exception;
It is recommended that you do not use the InitializingBean
interface because it unnecessarily couples the code to Spring. Alternatively, use the @PostConstruct
annotation or specify a POJO initialization method. In the case of XML-based configuration metadata, you use the init-method
attribute to specify the name of the method that has a void no-argument signature. With Java config, you use the initMethod
attribute of @Bean
, see the section called “Receiving lifecycle callbacks”. For example, the following:
建議你不使用InitializingBean
接口,因?yàn)樗鼘?duì)代碼與Spring進(jìn)行了不必要的耦合。作為一種替代方法,你可以使用@PostConstruct
注解或指定一個(gè)POPJO的初始化方法。在基于XML配置元數(shù)據(jù)的情況下,你可以使用init-method
特性來(lái)指定方法的名稱,方法是沒(méi)有返回值和參數(shù)的。如果使用Java配置,你可以使用@Bean
的initMethod
特性,請(qǐng)看"接收生命周期回調(diào)"小節(jié)。例如,下面的代碼:
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
public class ExampleBean {
public void init() {
// do some initialization work
}
}
…?is exactly the same as…?
等價(jià)于:
<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
public class AnotherExampleBean implements InitializingBean {
public void afterPropertiesSet() {
// do some initialization work
}
}
but does not couple the code to Spring.
但沒(méi)有與Spring代碼耦合。
Destruction callbacks
Implementing the org.springframework.beans.factory.DisposableBean
interface allows a bean to get a callback when the container containing it is destroyed. The DisposableBean
interface specifies a single method:
實(shí)現(xiàn)org.springframework.beans.factory.DisposableBean
接口允許容器包含的bean銷(xiāo)毀時(shí)調(diào)用回調(diào)函數(shù)。DisposableBean
接口指定了一個(gè)方法:
void destroy() throws Exception;
It is recommended that you do not use the DisposableBean
callback interface because it unnecessarily couples the code to Spring. Alternatively, use the @PreDestroy
annotation or specify a generic method that is supported by bean definitions. With XML-based configuration metadata, you use the destroy-method
attribute on the <bean/>
. With Java config, you use the destroyMethod
attribute of @Bean
, see the section called “Receiving lifecycle callbacks”. For example, the following definition:
建議你不使用DisposableBean
回調(diào)接口,因?yàn)樗鼘?duì)代碼與Spring進(jìn)行了不必要的耦合。作為一種替代方法,你可以使用@PreDestroy
注解或指定一個(gè)bean定義支持的通用方法。在基于XML配置元數(shù)據(jù)的情況下,你可以使用<bean/>
的destroy-method
特性。如果使用Java配置,你可以使用@Bean
的destroyMethod
特性,請(qǐng)看"接收生命周期回調(diào)"小節(jié)。例如,下面的定義:
<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>
public class ExampleBean {
public void cleanup() {
// do some destruction work (like releasing pooled connections)
}
}
is exactly the same as:
等價(jià)于:
<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
public class AnotherExampleBean implements DisposableBean {
public void destroy() {
// do some destruction work (like releasing pooled connections)
}
}
but does not couple the code to Spring.
但沒(méi)有與Spring代碼耦合。
The
destroy-method
attribute of a<bean>
element can be assigned a special(inferred)
value which instructs Spring to automatically detect a publicclose
orshutdown
method on the specific bean class (any class that implementsjava.lang.AutoCloseable
orjava.io.Closeable
would therefore match). This special(inferred)
value can also be set on thedefault-destroy-method
attribute of a<beans>
element to apply this behavior to an entire set of beans (see the section called “Default initialization and destroy methods”). Note that this is the default behavior with Java config.
<bean>
元素的destroy-method
特性可以分配一個(gè)特殊值(inferred)
,它會(huì)指導(dǎo)Spring自動(dòng)檢測(cè)指定的bean類(lèi)的公有close
方法或shutdown
方法(可以匹配任何實(shí)現(xiàn)java.lang.AutoCloseable
或java.io.Closeable
的類(lèi))。為了將這種行為應(yīng)用到beans的全部集合中,特殊值(inferred)
可以設(shè)置在<beans>
元素中的default-destroy-method
特性上(請(qǐng)看"默認(rèn)初始化方法和銷(xiāo)毀方法"小節(jié))。注意Java配置的默認(rèn)行為。
Default initialization and destroy methods
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.
當(dāng)你編寫(xiě)初始化回調(diào)函數(shù)和析構(gòu)回調(diào)函數(shù)時(shí),不要使用Spring特定的InitializingBean
和DisposableBean
回調(diào)接口,自己編寫(xiě)方法,方法名通常為init()
,initialize()
,dispose()
等等。理想情況下,這種生命周期回調(diào)方法的名稱在整個(gè)工程中是標(biāo)準(zhǔn)化的,以便所有開(kāi)發(fā)人員使用同樣的方法名稱,保證一致性。
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.
你可以配置Spring容器查找每個(gè)bean的初始化方法和析構(gòu)方法時(shí)的名字。這意味著,作為一個(gè)應(yīng)用開(kāi)發(fā)者,你可以編寫(xiě)應(yīng)用程序類(lèi)并使用名為init()
的初始化回調(diào)方法,而不必在每個(gè)bean定義中配置init-method="init"
特性。當(dāng)bean創(chuàng)建時(shí),Spring Ioc容器調(diào)用這個(gè)方法(按照前面描述的標(biāo)準(zhǔn)生命周期回調(diào)約定)。這個(gè)功能也強(qiáng)制了初始化方法和析構(gòu)方法命名規(guī)范的一致性。
Suppose that your initialization callback methods are named init()
and destroy callback methods are named destroy()
. Your class will resemble the class in the following example.
假設(shè)你的初始化回調(diào)方法名為init()
,析構(gòu)回調(diào)方法名為destroy()
。你的類(lèi)應(yīng)該與下面例子中的類(lèi)類(lèi)似。
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.");
}
}
}
<beans default-init-method="init">
<bean id="blogService" class="com.foo.DefaultBlogService">
<property name="blogDao" ref="blogDao" />
</bean>
</beans>
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 beans 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-init-method
特性,會(huì)讓Spring IoC容器將beans中的名為init
的方法識(shí)別為初始化回調(diào)方法。當(dāng)一個(gè)bean創(chuàng)建和組裝時(shí),如果bean類(lèi)有這樣一個(gè)方法,它會(huì)在恰當(dāng)?shù)臅r(shí)間被調(diào)用。
You configure destroy method callbacks similarly (in XML, that is) by using the default-destroy-method
attribute on the top-level <beans/>
element.
類(lèi)似的,你可以在頂層元素<beans/>
中設(shè)置default-destroy-method
特性來(lái)配置析構(gòu)回調(diào)方法的名字。
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 using the init-method
and destroy-method
attributes of the <bean/>
itself.
在現(xiàn)有的bean類(lèi)已經(jīng)有不符合命名規(guī)范的回調(diào)方法的情況下,你也可以通過(guò)在<bean/>
本身的init-method
和destroy-method
特性(在XML中)中指定方法名稱來(lái)覆蓋<beans/>
中的默認(rèn)名稱。
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, 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 with its proxy/interceptors and leave strange semantics when your code interacts directly to the raw target bean.
在bean被提供了所有依賴之后,Spring容器確保會(huì)立刻調(diào)用配置的初始化回調(diào)方法。因此初始化回調(diào)會(huì)在原生bean引用上調(diào)用,這意味著AOP攔截器等仍不能應(yīng)用到bean中。首先要完整的創(chuàng)建目標(biāo)bean,然后才會(huì)應(yīng)用AOP代理(例如)等攔截器鏈。如果分別定義了目標(biāo)bean和代理,你的代碼甚至能繞過(guò)代理直接與原生的目標(biāo)bean進(jìn)行交互。將攔截器應(yīng)用到初始化方法上可能會(huì)產(chǎn)生不一致性,因?yàn)檫@樣做會(huì)使目標(biāo)bean的生命周期與它的代理/攔截器相耦合,當(dāng)你的代碼與原生目標(biāo)bean直接進(jìn)行交互時(shí),語(yǔ)義會(huì)變的很奇怪。
Combining lifecycle mechanisms
As of Spring 2.5, you have three options for controlling bean lifecycle behavior: the InitializingBean
and DisposableBean
callback interfaces; custom init()
and destroy()
methods; and the @PostConstruct
and @PreDestroy
annotations. You can combine these mechanisms to control a given bean.
從Spring 2.5開(kāi)始,在控制bean的生命周期行為時(shí),你有三中選擇:InitializingBean和
DisposableBean回調(diào)接口;定制
init()和
destroy()方法;
@PostConstruct和
@PreDestroy`注解。在控制一個(gè)給定bean時(shí)你可以組合這些機(jī)制。
If multiple lifecycle mechanisms are configured for a bean, and each mechanism is configured with a different method name, then each configured method is executed in the order listed below. However, if the same method name is configured - for example,
init()
for an initialization method - for more than one of these lifecycle mechanisms, that method is executed once, as explained in the preceding section.
如果一個(gè)bean配置了多生命周期機(jī)制,每種機(jī)制配置了一個(gè)不同的方法名,那么每一個(gè)配置的方法會(huì)按照下面的順序列表來(lái)執(zhí)行。但是如果配置了相同的名字——例如,
init()
初始化方法——不止在一個(gè)生命周期機(jī)制中配置,那么這個(gè)方法只能執(zhí)行一次,像之前所說(shuō)的那樣。
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 interfaceA custom configured
init()
method
同一個(gè)bean配置了多生命周期機(jī)制,并有不同的初始化方法,那么調(diào)用順序如下:
先調(diào)用有注解
@PostConstruct
的方法然后調(diào)用
InitializingBean
回調(diào)接口定義的afterPropertiesSet()
方法最好調(diào)用定制配置的
init()
方法
Destroy methods are called in the same order:
Methods annotated with
@PreDestroy
destroy()
as defined by theDisposableBean
callback interfaceA custom configured
destroy()
method
析構(gòu)方法按同樣的順序調(diào)用:
先調(diào)用有
@PreDestroy
注解的方法再調(diào)用
DisposableBean
回調(diào)接口定義的destroy()
方法最好調(diào)用定制配置的
destroy()
方法
Startup and shutdown callbacks
The Lifecycle
interface defines the essential methods for any object that has its own lifecycle requirements (e.g. starts and stops some background process):
Lifecycle
接口定義了任何對(duì)象生命周期都需要的基本方法(例如啟動(dòng)和停止一些背景處理):
public interface Lifecycle {
void start();
void stop();
boolean isRunning();
}
Any Spring-managed object may implement that interface. Then, when the ApplicationContext
itself receives start and stop signals, e.g. for a stop/restart scenario at runtime, it will cascade those calls to all Lifecycle
implementations defined within that context. It does this by delegating to a LifecycleProcessor
:
任何Spring管理的對(duì)象都可以實(shí)現(xiàn)那個(gè)接口。當(dāng)ApplicationContext
本身收到啟動(dòng)啟動(dòng)和關(guān)閉信號(hào)時(shí),例如運(yùn)行時(shí)關(guān)閉/再啟動(dòng)場(chǎng)景,它將級(jí)聯(lián)調(diào)用所有的上下文定義的Lifecycle
實(shí)現(xiàn)。它通過(guò)委托LifecycleProcessor
來(lái)完成這個(gè)功能:
public interface LifecycleProcessor extends Lifecycle {
void onRefresh();
void onClose();
}
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.
注意LifecycleProcessor
本身是Lifecycle
接口的一個(gè)擴(kuò)展。它也添加了兩個(gè)其它的方法來(lái)響應(yīng)上下文的再刷新和關(guān)閉的。
Note that the regular
org.springframework.context.Lifecycle
interface is just a plain contract for explicit start/stop notifications and does NOT imply auto-startup at context refresh time. Consider implementingorg.springframework.context.SmartLifecycle
instead for fine-grained control over auto-startup of a specific bean (including startup phases). Also, please note that stop notifications are not guaranteed to come before destruction: On regular shutdown, allLifecycle
beans will first receive a stop notification before the general destruction callbacks are being propagated; however, on hot refresh during a context’s lifetime or on aborted refresh attempts, only destroy methods will be called.
注意正規(guī)的
org.springframework.context.Lifecycle
接口只是一個(gè)顯式啟動(dòng)/關(guān)閉通知的協(xié)議,并不意味著在上下文刷新時(shí)自動(dòng)啟動(dòng)。考慮實(shí)現(xiàn)org.springframework.context.SmartLifecycle
接口來(lái)實(shí)現(xiàn)對(duì)指定bean自動(dòng)啟動(dòng)的細(xì)粒度控制(包括啟動(dòng)時(shí)期)。請(qǐng)注意停止通知不能保證在銷(xiāo)毀之前到來(lái):在正式關(guān)閉時(shí),所有的Lifecycle
beans在通常的析構(gòu)回調(diào)傳播之前首先會(huì)收到停止通知;但是,在上下文使用期間進(jìn)行熱刷新或嘗試取消再刷新,只會(huì)調(diào)用析構(gòu)方法。
The order of startup and shutdown invocations can be important. If a "depends-on" relationship exists between any two objects, the dependent side will start after its dependency, and it will stop 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
.
啟動(dòng)和關(guān)閉的調(diào)用順序是很重要的。如果任何兩個(gè)對(duì)象間存在一個(gè)"depends-on"關(guān)系,那么依賴關(guān)系將在它的依賴之后開(kāi)始,在它的依賴之前停止。然而有時(shí)直接的依賴關(guān)系是未知的。你可能只知道某個(gè)類(lèi)型的對(duì)象應(yīng)該在另一個(gè)類(lèi)型的對(duì)象之前啟動(dòng)。在那種情況下,SmartLifecycle
接口定義了另一種選擇,也就是說(shuō)getPhase()
定義在它的父接口Phased
中。
public interface Phased {
int getPhase();
}
public interface SmartLifecycle extends Lifecycle, Phased {
boolean isAutoStartup();
void stop(Runnable callback);
}
When starting, the objects with the lowest phase start first, and 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’s also important to know that the default phase for any "normal" Lifecycle
object that does not implement SmartLifecycle
would be 0. Therefore, any negative phase value would indicate that an object should start before those standard components (and stop after them), and vice versa for any positive phase value.
當(dāng)開(kāi)始時(shí),最低相位的對(duì)象先啟動(dòng),當(dāng)停止時(shí),最高相位的對(duì)象先停止。因此,實(shí)現(xiàn)了SmartLifecycle
接口,getPhase()
方法返回值為Integer.MIN_VALUE
的對(duì)象將最先啟動(dòng)并最后停止。另一方面,相位值Integer.MAX_VALUE
表明對(duì)象應(yīng)該最后啟動(dòng),最先停止(可能是因?yàn)樗蕾嚻渌\(yùn)行的進(jìn)程)。當(dāng)考慮相位值時(shí),知道任何沒(méi)有實(shí)現(xiàn)SmartLifecycle
接口的Lifecycle
對(duì)象的默認(rèn)值為0是很重要的。因此,任何負(fù)相位值表示對(duì)象應(yīng)該在那么標(biāo)準(zhǔn)組件之前啟動(dòng)(在它們之后停止),反之為任何正相位值。
As you can see 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
, will wait 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 only want to modify the timeout, then defining the following would be sufficient:
正如你看到的,在SmartLifecycle
中定義的停止方法接收一個(gè)回調(diào)函數(shù)。任何實(shí)現(xiàn)在關(guān)閉進(jìn)程完成之后都必須調(diào)用回調(diào)的run()
方法。當(dāng)需要時(shí)這可以進(jìn)行異步關(guān)閉,因?yàn)?code>LifecycleProcessor接口、DefaultLifecycleProcessor
接口的默認(rèn)實(shí)現(xiàn)會(huì)等待每個(gè)階段的對(duì)象組直到達(dá)到超時(shí)值,然后調(diào)用回調(diào)函數(shù)。默認(rèn)每個(gè)時(shí)期的超時(shí)值為30秒。你可以在上下文中通過(guò)定義名為"lifecycleProcessor"的bean來(lái)覆蓋默認(rèn)的生命周期處理器實(shí)例。如果你只想修改超時(shí)值,如下定義是足夠的:
<bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor">
<!-- timeout value in milliseconds -->
<property name="timeoutPerShutdownPhase" value="10000"/>
</bean>
As mentioned, the LifecycleProcessor
interface defines callback methods for the refreshing and closing of the context as well. The latter will simply drive the shutdown process as if stop()
had been called explicitly, but it will happen 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 will be invoked, and at that point the default lifecycle processor will check the boolean value returned by each SmartLifecycle
object’s isAutoStartup()
method. If "true", then that object will be 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 as well as any "depends-on" relationships will determine the startup order in the same way as described above.
像上面提到的那樣,LifecycleProcessor
接口為再刷新和上下文的關(guān)閉也定義了回調(diào)方法。后者會(huì)簡(jiǎn)單的驅(qū)動(dòng)關(guān)閉進(jìn)程就像顯式的調(diào)用了stop()
方法一樣,但當(dāng)上下文關(guān)閉時(shí)它才會(huì)發(fā)生。另一方面refresh
回調(diào)能使SmartLifecycle
beans的另一個(gè)功能可用。當(dāng)上下文再刷新時(shí)(所有對(duì)象已經(jīng)實(shí)例化并初始化),回調(diào)函數(shù)將被調(diào)用,那時(shí)默認(rèn)的生命周期處理器將會(huì)檢查每個(gè)SmartLifecycle
對(duì)象的isAutoStartup()
方法返回的布爾值。如果為true
,對(duì)象將會(huì)在那時(shí)啟動(dòng)而不是等待上下文的顯式調(diào)用或它自己的start()
方法(不像上下文再刷新,對(duì)于一個(gè)標(biāo)準(zhǔn)的上下文實(shí)現(xiàn)上下啟動(dòng)不會(huì)自動(dòng)發(fā)生)。"phase"值以及"depends-on"關(guān)系將決定啟動(dòng)順序,像上面描述的一樣。
Shutting down the Spring IoC container gracefully in non-web applications
This section applies only to non-web applications. Spring’s web-based
ApplicationContext
implementations already have code in place to shut down the Spring IoC container gracefully when the relevant web application is shut down.
這一節(jié)只應(yīng)用于非web應(yīng)用。Spring的基于web的
ApplicationContext
實(shí)現(xiàn)已經(jīng)有代碼來(lái)處理當(dāng)相關(guān)的web應(yīng)用關(guān)閉時(shí),妥善關(guān)閉Spring IoC容器的問(wèn)題。
If you are using Spring’s IoC container in a non-web application environment; for example, in a rich client desktop environment; you 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. Of course, you must still configure and implement these destroy callbacks correctly.
如果你在非web應(yīng)用環(huán)境使用Spring的IoC容器;例如,在一個(gè)富桌面客戶端環(huán)境中,你在JVM中注冊(cè)一個(gè)關(guān)閉鉤子。這樣做確保了妥善的關(guān)閉,為了釋放所有資源需要調(diào)用與單例beans相關(guān)的析構(gòu)方法。當(dāng)然,你仍然必須正確的配置和實(shí)現(xiàn)這些銷(xiāo)毀回調(diào)函數(shù)。
To register a shutdown hook, you call the registerShutdownHook()
method that is declared on the ConfigurableApplicationContext
interface:
為了注冊(cè)一個(gè)關(guān)閉鉤子,你可以調(diào)用ConfigurableApplicationContext
接口中聲明的registerShutdownHook()
方法:
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(
new String []{"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...
}
}
3.6.2 ApplicationContextAware and BeanNameAware
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
.
當(dāng)ApplicationContext
創(chuàng)建一個(gè)實(shí)現(xiàn)org.springframework.context.ApplicationContextAware
接口的對(duì)象實(shí)例時(shí),這個(gè)實(shí)例會(huì)提供一個(gè)ApplicationContext
的引用。
public interface ApplicationContextAware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
Thus beans can manipulate programmatically 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 Section 3.15, “Additional Capabilities of the ApplicationContext”.
因此beans可以以編程方式操縱創(chuàng)建它們的ApplicationContext
,通過(guò)ApplicationContext
接口,或通過(guò)將引用拋給這個(gè)接口的一個(gè)已知子類(lèi),例如ConfigurableApplicationContext
,它暴露了額外的功能。一個(gè)方法是編程式檢索其他的bean。有時(shí)這個(gè)能力是很有用的,但是通常你應(yīng)該避免使用它,因?yàn)樗詈狭舜a和Spring,不能遵循控制反轉(zhuǎn)的風(fēng)格,在控制反轉(zhuǎn)中協(xié)作者是作為屬性提供給beans的。ApplicationContext
的其它方法提供了對(duì)文件資源的訪問(wèn),發(fā)布應(yīng)用事件,訪問(wèn)MessageSource
的功能。這些額外的特性將在3.15小節(jié)『ApplicationContext”的額外能力』中描述。
As of Spring 2.5, autowiring is another alternative to obtain reference to the ApplicationContext
. The "traditional" constructor
and byType
autowiring modes (as described in Section 3.4.5, “Autowiring collaborators”) can provide a dependency of type ApplicationContext
for a constructor argument or setter method parameter, respectively. For more flexibility, including the ability to autowire fields and multiple parameter methods, use the new annotation-based autowiring features. If you do, the ApplicationContext
is autowired into a field, constructor argument, or method parameter that is expecting the ApplicationContext
type if the field, constructor, or method in question carries the @Autowired
annotation. For more information, see Section 3.9.2, “@Autowired”.
從Spring 2.5起,自動(dòng)裝配是另一種可替代的獲得ApplicationContext
引用的方法。『傳統(tǒng)的』constructor
和byType
自動(dòng)裝配模式(如3.4.5小節(jié)所述,『自動(dòng)裝配協(xié)作者』)可以分別為構(gòu)造函數(shù)參數(shù)或setter方法參數(shù)提供ApplicationContext
類(lèi)型的依賴。更多的靈活性包括自動(dòng)裝配變量的能力和多參數(shù)方法,使用新的基于注解的自動(dòng)裝配特性。如果你這一做的話,ApplicationContext
可以被自動(dòng)裝配到變量中,構(gòu)造函數(shù)參數(shù)中或方法參數(shù)中,如果討論的變量,構(gòu)造函數(shù)或方法有@Autowired
注解,那么可以期望它是ApplicationContext
類(lèi)型。更多信息請(qǐng)看3.9.2小節(jié),@autowired
。
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.
當(dāng)ApplicationContext
創(chuàng)建一個(gè)實(shí)現(xiàn)了org.springframework.beans.factory.BeanNameAware
接口的類(lèi)時(shí),類(lèi)中有相關(guān)的對(duì)象定義中定義的名稱的引用。
public interface BeanNameAware {
void setBeanName(String name) throws BeansException;
}
The callback is invoked after population of normal bean properties but before an initialization callback such as InitializingBean
afterPropertiesSet or a custom init-method.
在正常的bean屬性填入之后,回調(diào)方法調(diào)用,但在初始化回調(diào)方法之前,例如InitializingBean
的afterPropertiesSet或一個(gè)定制的初始化方法。
3.6.3 Other Aware interfaces
Besides ApplicationContextAware
and BeanNameAware
discussed above, Spring offers a range of Aware
interfaces that allow beans to indicate to the container that they require a certain infrastructure dependency. The most important Aware
interfaces are summarized below - as a general rule, the name is a good indication of the dependency type:
除了上面討論的ApplicationContextAware
和BeanNameAware
之外,Spring給予了一系列Aware
接口來(lái)允許beans向容器表明它們需要一個(gè)確定的基礎(chǔ)結(jié)構(gòu)依賴。最重要的Aware
接口總結(jié)如下——作為一個(gè)通用規(guī)則,名字是依賴類(lèi)型的一個(gè)很好暗示:
Table 3.4. Aware interfaces
Name | Injected Dependency | Explained in |
---|---|---|
ApplicationContextAware | Declaring ApplicationContext | Section 3.6.2, “ApplicationContextAware and BeanNameAware” |
ApplicationEventPublisherAware | Event publisher of the enclosing ApplicationContext | Section 3.15, “Additional Capabilities of the ApplicationContext” |
BeanClassLoaderAware | Class loader used to load the bean classes. | Section 3.3.2, “Instantiating beans” |
BeanFactoryAware | Declaring BeanFactory | Section 3.6.2, “ApplicationContextAware and BeanNameAware” |
BeanNameAware | Name of the declaring bean | Section 3.6.2, “ApplicationContextAware and BeanNameAware” |
BootstrapContextAware | Resource adapter BootstrapContext the container runs in. Typically available only in JCA aware ApplicationContexts | Chapter 28, JCA CCI |
LoadTimeWeaverAware | Defined weaver for processing class definition at load time | Section 7.8.4, “Load-time weaving with AspectJ in the Spring Framework” |
MessageSourceAware | Configured strategy for resolving messages (with support for parametrization and internationalization) | Section 3.15, “Additional Capabilities of the ApplicationContext” |
NotificationPublisherAware | Spring JMX notification publisher | Section 27.7, “Notifications” |
ResourceLoaderAware | Configured loader for low-level access to resources | Chapter 4, Resources |
ServletConfigAware | Current ServletConfig the container runs in. Valid only in a web-aware Spring ApplicationContext | Chapter 18, Web MVC framework |
ServletContextAware | Current ServletContext the container runs in. Valid only in a web-aware Spring ApplicationContext | Chapter 18, Web MVC framework |
表3.4. Aware接口
Name | Injected Dependency | Explained in |
---|---|---|
ApplicationContextAware | 聲明ApplicationContext
|
Section 3.6.2, “ApplicationContextAware and BeanNameAware” |
ApplicationEventPublisherAware | 封裝事件發(fā)布的ApplicationContext
|
Section 3.15, “Additional Capabilities of the ApplicationContext” |
BeanClassLoaderAware | 用來(lái)加載bean的類(lèi)加載器 | Section 3.3.2, “Instantiating beans” |
BeanFactoryAware | 聲明BeanFactory
|
Section 3.6.2, “ApplicationContextAware and BeanNameAware” |
BeanNameAware | 聲明的bean的名字 | Section 3.6.2, “ApplicationContextAware and BeanNameAware” |
BootstrapContextAware | 容器運(yùn)行的資源自適應(yīng)BootstrapContext . 通常只在JCA aware ApplicationContexts 可獲得 |
Chapter 28, JCA CCI |
LoadTimeWeaverAware | 加載時(shí)為處理類(lèi)定義定義的weaver | Section 7.8.4, “Load-time weaving with AspectJ in the Spring Framework” |
MessageSourceAware | 解析消息配置策略 (支持參數(shù)化和國(guó)際化) | Section 3.15, “Additional Capabilities of the ApplicationContext” |
NotificationPublisherAware | Spring JMX通知發(fā)布器 | Section 27.7, “Notifications” |
ResourceLoaderAware | 為底層訪問(wèn)資源配置的加載器 | Chapter 4, Resources |
ServletConfigAware | 容器運(yùn)行的當(dāng)前ServletConfig 。 僅在web感知的Spring ApplicationContext 中有效 |
Chapter 18, Web MVC framework |
ServletContextAware | 容器運(yùn)行的當(dāng)前ServletContext 。 僅在web感知的Spring ApplicationContext 中有效 |
Chapter 18, Web MVC framework |
Note again that usage of these interfaces ties your code to the Spring API and does not follow the Inversion of Control style. As such, they are recommended for infrastructure beans that require programmatic access to the container.
注意這些接口的用法將你的代碼與Spring進(jìn)行了捆綁,不符合控制反轉(zhuǎn)的風(fēng)格。因此,它們是為那么需要以編程方式訪問(wèn)容器的基礎(chǔ)結(jié)構(gòu)beans推薦的。