org.springframework.context.SmartLifecycle Maven / Gradle / Ivy
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context;
/**
* An extension of the {@link Lifecycle} interface for those objects that require
* to be started upon {@code ApplicationContext} refresh and/or shutdown in a
* particular order.
*
* The {@link #isAutoStartup()} return value indicates whether this object should
* be started at the time of a context refresh. The callback-accepting
* {@link #stop(Runnable)} method is useful for objects that have an asynchronous
* shutdown process. Any implementation of this interface must invoke the
* callback's {@code run()} method upon shutdown completion to avoid unnecessary
* delays in the overall {@code ApplicationContext} shutdown.
*
*
This interface extends {@link Phased}, and the {@link #getPhase()} method's
* return value indicates the phase within which this {@code Lifecycle} component
* should be started and stopped. The startup process begins with the lowest
* phase value and ends with the highest phase value ({@code Integer.MIN_VALUE}
* is the lowest possible, and {@code Integer.MAX_VALUE} is the highest possible).
* The shutdown process will apply the reverse order. Any components with the
* same value will be arbitrarily ordered within the same phase.
*
*
Example: if component B depends on component A having already started,
* then component A should have a lower phase value than component B. During
* the shutdown process, component B would be stopped before component A.
*
*
Any explicit "depends-on" relationship will take precedence over the phase
* order such that the dependent bean always starts after its dependency and
* always stops before its dependency.
*
*
Any {@code Lifecycle} components within the context that do not also
* implement {@code SmartLifecycle} will be treated as if they have a phase
* value of {@code 0}. This allows a {@code SmartLifecycle} component to start
* before those {@code Lifecycle} components if the {@code SmartLifecycle}
* component has a negative phase value, or the {@code SmartLifecycle} component
* may start after those {@code Lifecycle} components if the {@code SmartLifecycle}
* component has a positive phase value.
*
*
Note that, due to the auto-startup support in {@code SmartLifecycle}, a
* {@code SmartLifecycle} bean instance will usually get initialized on startup
* of the application context in any case. As a consequence, the bean definition
* lazy-init flag has very limited actual effect on {@code SmartLifecycle} beans.
*
* @author Mark Fisher
* @author Juergen Hoeller
* @author Sam Brannen
* @since 3.0
* @see LifecycleProcessor
* @see ConfigurableApplicationContext
*/
public interface SmartLifecycle extends Lifecycle, Phased {
/**
* The default phase for {@code SmartLifecycle}: {@code Integer.MAX_VALUE}.
*
This is different from the common phase {@code 0} associated with regular
* {@link Lifecycle} implementations, putting the typically auto-started
* {@code SmartLifecycle} beans into a later startup phase and an earlier
* shutdown phase.
*
Note that certain {@code SmartLifecycle} components come with a different
* default phase: for example, executors/schedulers with {@code Integer.MAX_VALUE / 2}.
* @since 5.1
* @see #getPhase()
* @see org.springframework.scheduling.concurrent.ExecutorConfigurationSupport#DEFAULT_PHASE
* @see org.springframework.context.support.DefaultLifecycleProcessor#setTimeoutPerShutdownPhase
*/
int DEFAULT_PHASE = Integer.MAX_VALUE;
/**
* Returns {@code true} if this {@code Lifecycle} component should get
* started automatically by the container at the time that the containing
* {@link ApplicationContext} gets refreshed.
*
A value of {@code false} indicates that the component is intended to
* be started through an explicit {@link #start()} call instead, analogous
* to a plain {@link Lifecycle} implementation.
*
The default implementation returns {@code true}.
* @see #start()
* @see #getPhase()
* @see LifecycleProcessor#onRefresh()
* @see ConfigurableApplicationContext#refresh()
*/
default boolean isAutoStartup() {
return true;
}
/**
* Indicates that a Lifecycle component must stop if it is currently running.
*
The provided callback is used by the {@link LifecycleProcessor} to support
* an ordered, and potentially concurrent, shutdown of all components having a
* common shutdown order value. The callback must be executed after
* the {@code SmartLifecycle} component does indeed stop.
*
The {@link LifecycleProcessor} will call only this variant of the
* {@code stop} method; i.e. {@link Lifecycle#stop()} will not be called for
* {@code SmartLifecycle} implementations unless explicitly delegated to within
* the implementation of this method.
*
The default implementation delegates to {@link #stop()} and immediately
* triggers the given callback in the calling thread. Note that there is no
* synchronization between the two, so custom implementations may at least
* want to put the same steps within their common lifecycle monitor (if any).
* @see #stop()
* @see #getPhase()
*/
default void stop(Runnable callback) {
stop();
callback.run();
}
/**
* Return the phase that this lifecycle object is supposed to run in.
*
The default implementation returns {@link #DEFAULT_PHASE} in order to
* let {@code stop()} callbacks execute before regular {@code Lifecycle}
* implementations.
* @see #isAutoStartup()
* @see #start()
* @see #stop(Runnable)
* @see org.springframework.context.support.DefaultLifecycleProcessor#getPhase(Lifecycle)
*/
@Override
default int getPhase() {
return DEFAULT_PHASE;
}
}