Skip to content

Commit f6a2e58

Browse files
committed
SPR-6341 Added documentation for Lifecycle, SmartLifecycle, and LifecycleProcessor in the 'beans' chapter after init/destroy callbacks are covered.
1 parent a64f0f1 commit f6a2e58

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

spring-framework-reference/src/beans.xml

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3206,6 +3206,12 @@ beanFactory.registerScope("<emphasis role="bold">thread</emphasis>", threadScope
32063206
<interfacename>BeanPostProcessor</interfacename> yourself. For more
32073207
information, see <xref linkend="beans-factory-extension" />.</para>
32083208

3209+
<para>In addition to the initialization and destruction callbacks,
3210+
Spring-managed objects may also implement the
3211+
<interfacename>Lifecycle</interfacename> interface so that those
3212+
objects can participate in the startup and shutdown process as
3213+
driven by the container's own lifecycle.</para>
3214+
32093215
<para>The lifecycle callback interfaces are described in this
32103216
section.</para>
32113217

@@ -3447,6 +3453,116 @@ beanFactory.registerScope("<emphasis role="bold">thread</emphasis>", threadScope
34473453
</itemizedlist>
34483454
</section>
34493455

3456+
<section id="beans-factory-lifecycle-processor">
3457+
<title>Startup and shutdown callbacks</title>
3458+
3459+
<para>The <interfacename>Lifecycle</interfacename> interface defines
3460+
the essential methods for any object that has its own lifecycle
3461+
requirements (e.g. starts and stops some background process):</para>
3462+
3463+
<programlisting language="java">public interface Lifecycle {
3464+
3465+
void start();
3466+
3467+
void stop();
3468+
3469+
boolean isRunning();
3470+
3471+
}</programlisting>
3472+
3473+
<para>Any Spring-managed object may implement that interface. Then,
3474+
when the ApplicationContext itself starts and stops, it will cascade
3475+
those calls to all Lifecycle implementations defined within that context.
3476+
It does this by delegating to a <interfacename>LifecycleProcessor</interfacename>:
3477+
</para>
3478+
3479+
<programlisting language="java">public interface LifecycleProcessor extends Lifecycle {
3480+
3481+
void onRefresh();
3482+
3483+
void onClose();
3484+
3485+
}</programlisting>
3486+
3487+
<para>Notice that the <interfacename>LifecycleProcessor</interfacename>
3488+
is itself an extension of the <interfacename>Lifecycle</interfacename>
3489+
interface. It also adds two other methods for reacting to the context
3490+
being refreshed and closed.</para>
3491+
3492+
<para>The order of startup and shutdown invocations can be important.
3493+
If a "depends-on" relationship exists between any two objects, the
3494+
dependent side will start <emphasis>after</emphasis> its dependency,
3495+
and it will stop <emphasis>before</emphasis> its dependency. However,
3496+
at times the direct dependencies are unknown. You may only know that
3497+
objects of a certain type should start prior to objects of another
3498+
type. In those cases, the <interfacename>SmartLifecycle</interfacename>
3499+
interface defines another option, namely the <methodname>getPhase()</methodname>
3500+
method as defined on its super-interface, <interfacename>Phased</interfacename>.
3501+
</para>
3502+
3503+
<programlisting language="java">public interface Phased {
3504+
3505+
int getPhase();
3506+
3507+
}
3508+
3509+
3510+
public interface SmartLifecycle extends Lifecycle, Phased {
3511+
3512+
boolean isAutoStartup();
3513+
3514+
void stop(Runnable callback);
3515+
3516+
}</programlisting>
3517+
3518+
<para>When starting, the objects with the lowest phase start first, and
3519+
when stopping, the reverse order is followed. Therefore, an object that
3520+
implements <interfacename>SmartLifecycle</interfacename> and whose getPhase()
3521+
method returns <literal>Integer.MIN_VALUE</literal> would be among the first
3522+
to start and the last to stop. At the other end of the spectrum, a phase
3523+
value of <literal>Integer.MAX_VALUE</literal> would indicate that the
3524+
object should be started last and stopped first (likely because it
3525+
depends on other processes to be running). When considering the phase value,
3526+
it's also important to know that the default phase for any "normal"
3527+
<interfacename>Lifecycle</interfacename> object that does not implement
3528+
<interfacename>SmartLifecycle</interfacename> would be 0. Therefore, any
3529+
negative phase value would indicate that an object should start before
3530+
those standard components (and stop after them), and vice versa for any
3531+
positive phase value.</para>
3532+
3533+
<para>As you can see the stop method defined by <interfacename>SmartLifecycle</interfacename>
3534+
accepts a callback. Any implementation <emphasis>must</emphasis> invoke that
3535+
callback's run() method after that implementation's shutdown process is complete.
3536+
That enables asynchronous shutdown where necessary since the default
3537+
implementation of the <interfacename>LifecycleProcessor</interfacename>
3538+
interface, <classname>DefaultLifecycleProcessor</classname>, will wait
3539+
up to its timeout value for the group of objects within each phase to
3540+
invoke that callback. The default per-phase timeout is 30 seconds. You
3541+
can override the default lifecycle processor instance by defining a bean
3542+
named "lifecycleProcessor" within the context. If you only want to modify
3543+
the timeout, then defining the following would be sufficient:</para>
3544+
3545+
<programlisting language="xml"><![CDATA[<bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor">
3546+
<!-- timeout value in milliseconds -->
3547+
<property name="timeoutPerShutdownPhase" value="10000"/>
3548+
</bean>]]></programlisting>
3549+
3550+
<para>As mentioned, the <interfacename>LifecycleProcessor</interfacename> interface
3551+
defines callback methods for the refreshing and closing of the context as well. The
3552+
latter will simply drive the shutdown process as if stop() had been called explicitly,
3553+
but it will happen when the context is closing. The 'refresh' callback on the other
3554+
hand enables another feature of <interfacename>SmartLifecycle</interfacename> beans.
3555+
When the context is refreshed (after all objects have been instantiated and initialized),
3556+
that callback will be invoked, and at that point the default lifecycle processor will
3557+
check the boolean value returned by each <interfacename>SmartLifecycle</interfacename>
3558+
object's <methodname>isAutoStartup()</methodname> method. If "true", then that object
3559+
will be started at that point rather than waiting for an explicit invocation of the
3560+
context's or its own start() method (unlike the context refresh, the context start does
3561+
not happen automatically for a standard context implementation). The "phase" value as
3562+
well as any "depends-on" relationships will determine the startup order in the same way
3563+
as described above.</para>
3564+
</section>
3565+
34503566
<section id="beans-factory-shutdown">
34513567
<title>Shutting down the Spring IoC container gracefully in non-web
34523568
applications</title>

0 commit comments

Comments
 (0)