SPR-6341 Added documentation for Lifecycle, SmartLifecycle, and LifecycleProcessor in the 'beans' chapter after init/destroy callbacks are covered.
This commit is contained in:
parent
a64f0f1ebe
commit
f6a2e58d95
|
|
@ -3206,6 +3206,12 @@ beanFactory.registerScope("<emphasis role="bold">thread</emphasis>", threadScope
|
||||||
<interfacename>BeanPostProcessor</interfacename> yourself. For more
|
<interfacename>BeanPostProcessor</interfacename> yourself. For more
|
||||||
information, see <xref linkend="beans-factory-extension" />.</para>
|
information, see <xref linkend="beans-factory-extension" />.</para>
|
||||||
|
|
||||||
|
<para>In addition to the initialization and destruction callbacks,
|
||||||
|
Spring-managed objects may also implement the
|
||||||
|
<interfacename>Lifecycle</interfacename> interface so that those
|
||||||
|
objects can participate in the startup and shutdown process as
|
||||||
|
driven by the container's own lifecycle.</para>
|
||||||
|
|
||||||
<para>The lifecycle callback interfaces are described in this
|
<para>The lifecycle callback interfaces are described in this
|
||||||
section.</para>
|
section.</para>
|
||||||
|
|
||||||
|
|
@ -3447,6 +3453,116 @@ beanFactory.registerScope("<emphasis role="bold">thread</emphasis>", threadScope
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section id="beans-factory-lifecycle-processor">
|
||||||
|
<title>Startup and shutdown callbacks</title>
|
||||||
|
|
||||||
|
<para>The <interfacename>Lifecycle</interfacename> interface defines
|
||||||
|
the essential methods for any object that has its own lifecycle
|
||||||
|
requirements (e.g. starts and stops some background process):</para>
|
||||||
|
|
||||||
|
<programlisting language="java">public interface Lifecycle {
|
||||||
|
|
||||||
|
void start();
|
||||||
|
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
boolean isRunning();
|
||||||
|
|
||||||
|
}</programlisting>
|
||||||
|
|
||||||
|
<para>Any Spring-managed object may implement that interface. Then,
|
||||||
|
when the ApplicationContext itself starts and stops, it will cascade
|
||||||
|
those calls to all Lifecycle implementations defined within that context.
|
||||||
|
It does this by delegating to a <interfacename>LifecycleProcessor</interfacename>:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<programlisting language="java">public interface LifecycleProcessor extends Lifecycle {
|
||||||
|
|
||||||
|
void onRefresh();
|
||||||
|
|
||||||
|
void onClose();
|
||||||
|
|
||||||
|
}</programlisting>
|
||||||
|
|
||||||
|
<para>Notice that the <interfacename>LifecycleProcessor</interfacename>
|
||||||
|
is itself an extension of the <interfacename>Lifecycle</interfacename>
|
||||||
|
interface. It also adds two other methods for reacting to the context
|
||||||
|
being refreshed and closed.</para>
|
||||||
|
|
||||||
|
<para>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 <emphasis>after</emphasis> its dependency,
|
||||||
|
and it will stop <emphasis>before</emphasis> 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 <interfacename>SmartLifecycle</interfacename>
|
||||||
|
interface defines another option, namely the <methodname>getPhase()</methodname>
|
||||||
|
method as defined on its super-interface, <interfacename>Phased</interfacename>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<programlisting language="java">public interface Phased {
|
||||||
|
|
||||||
|
int getPhase();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface SmartLifecycle extends Lifecycle, Phased {
|
||||||
|
|
||||||
|
boolean isAutoStartup();
|
||||||
|
|
||||||
|
void stop(Runnable callback);
|
||||||
|
|
||||||
|
}</programlisting>
|
||||||
|
|
||||||
|
<para>When starting, the objects with the lowest phase start first, and
|
||||||
|
when stopping, the reverse order is followed. Therefore, an object that
|
||||||
|
implements <interfacename>SmartLifecycle</interfacename> and whose getPhase()
|
||||||
|
method returns <literal>Integer.MIN_VALUE</literal> would be among the first
|
||||||
|
to start and the last to stop. At the other end of the spectrum, a phase
|
||||||
|
value of <literal>Integer.MAX_VALUE</literal> 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"
|
||||||
|
<interfacename>Lifecycle</interfacename> object that does not implement
|
||||||
|
<interfacename>SmartLifecycle</interfacename> 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.</para>
|
||||||
|
|
||||||
|
<para>As you can see the stop method defined by <interfacename>SmartLifecycle</interfacename>
|
||||||
|
accepts a callback. Any implementation <emphasis>must</emphasis> 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 <interfacename>LifecycleProcessor</interfacename>
|
||||||
|
interface, <classname>DefaultLifecycleProcessor</classname>, 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:</para>
|
||||||
|
|
||||||
|
<programlisting language="xml"><![CDATA[<bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor">
|
||||||
|
<!-- timeout value in milliseconds -->
|
||||||
|
<property name="timeoutPerShutdownPhase" value="10000"/>
|
||||||
|
</bean>]]></programlisting>
|
||||||
|
|
||||||
|
<para>As mentioned, the <interfacename>LifecycleProcessor</interfacename> 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 <interfacename>SmartLifecycle</interfacename> 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 <interfacename>SmartLifecycle</interfacename>
|
||||||
|
object's <methodname>isAutoStartup()</methodname> 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.</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section id="beans-factory-shutdown">
|
<section id="beans-factory-shutdown">
|
||||||
<title>Shutting down the Spring IoC container gracefully in non-web
|
<title>Shutting down the Spring IoC container gracefully in non-web
|
||||||
applications</title>
|
applications</title>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue