Spring IoC контейнер: настройка бинов, обратные вызовы при запуске и завершении работы

Интерфейс Lifecycle определяет основные методы для любого объекта, который имеет свои собственные требования жизненного цикла (например, запуск и остановка некоторого фонового процесса):

Java

public interface Lifecycle {

    void start();

    void stop();

    boolean isRunning();
}

Kotlin

interface Lifecycle {

    fun start()

    fun stop()

    val isRunning: Boolean
}

Любой объект, управляемый Spring, может реализовать интерфейс Lifecycle. Затем, когда сам ApplicationContext получает сигналы запуска и остановки (например, для сценария остановки/перезапуска во время выполнения), он связывает эти вызовы со всеми реализациями жизненного цикла, определенными в этом контексте. Это делается путем делегирования LifecycleProcessor, как показано в следующем листинге:

Java

public interface LifecycleProcessor extends Lifecycle {

    void onRefresh();

    void onClose();
}

Kotlin

interface LifecycleProcessor : Lifecycle {

    fun onRefresh()

    fun onClose()
}

Обратите внимание, что LifecycleProcessor сам по себе является расширением интерфейса Lifecycle. Он также добавляет два других метода для реакции на обновляемый и закрытый контекст.

Обратите внимание, что обычный интерфейс org.springframework.context.Lifecycle представляет собой простой контракт для явных уведомлений о запуске и останове и не подразумевает автоматический запуск во время обновления контекста. Для более детального управления автоматическим запуском определенного bean-компонента (включая фазы запуска) рассмотрите вариант реализации org.springframework.context.SmartLifecycle.

Также обратите внимание, что уведомления об остановке не гарантируются до уничтожения. При обычном отключении все компоненты жизненного цикла сначала получают уведомление о остановке до того, как распространяются обратные вызовы общего уничтожения. Однако при горячем обновлении во время существования контекста или при прерванных попытках обновления вызываются только методы уничтожения.

Порядок запуска и завершения вызовов может быть важным. Если между любыми двумя объектами существует отношение "зависит от", зависимая сторона начинается после своей зависимости и останавливается до ее зависимости. Однако порой прямые зависимости неизвестны. Вы можете знать только, что объекты определенного типа должны начинаться до объектов другого типа. В этих случаях интерфейс SmartLifecycle определяет другую опцию, а именно метод getPhase(), как определено в его суперинтерфейсе, Phased. В следующем листинге показано определение поэтапного интерфейса:

Java

public interface Phased {

    int getPhase();
}

Kotlin

interface Phased {

    val phase: Int
}

В следующем листинге показано определение интерфейса SmartLifecycle:

Java

public interface SmartLifecycle extends Lifecycle, Phased {

    boolean isAutoStartup();

    void stop(Runnable callback);
}

Kotlin

interface SmartLifecycle : Lifecycle, Phased {

    val isAutoStartup: Boolean

    fun stop(callback: Runnable)
}

При запуске объекты с самой низкой фазой запускаются первыми. При остановке следует обратный порядок. Следовательно, объект, который реализует SmartLifecycle и чей метод getPhase() возвращает Integer.MIN_VALUE, будет одним из первых для запуска и последним для остановки. На другом конце спектра значение фазы Integer.MAX_VALUE будет указывать, что объект должен запускаться последним и останавливаться первым (вероятно, потому что это зависит от других процессов, которые будут запущены). При рассмотрении значения фазы также важно знать, что фаза по умолчанию для любого "нормального" объекта жизненного цикла, который не реализует SmartLifecycle, равна 0. Поэтому любое отрицательное значение фазы указывает, что объект должен запускаться до этих стандартных компонентов (и останавливаться после них). Обратное верно для любого положительного значения фазы.

Метод stop, определенный SmartLifecycle, принимает обратный вызов. Любая реализация должна вызывать метод run() этого обратного вызова после окончания процесса завершения этой реализации. Это позволяет при необходимости выполнять асинхронное отключение, поскольку реализация по умолчанию интерфейса LifecycleProcessor, DefaultLifecycleProcessor, ожидает до своего значения тайм-аута для группы объектов в каждой фазе, чтобы вызвать этот обратный вызов. Тайм-аут для каждой фазы по умолчанию составляет 30 секунд. Вы можете переопределить экземпляр процессора жизненного цикла по умолчанию, определив bean-компонент с именем lifecycleProcessor в контексте. Если вы хотите только изменить время ожидания, достаточно указать следующее:

<bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor">
    <!-- значение тайм-аута в миллисекундах -->
    <property name="timeoutPerShutdownPhase" value="10000"/>
</bean>

Как упоминалось ранее, интерфейс LifecycleProcessor также определяет методы обратного вызова для обновления и закрытия контекста. Последний управляет процессом завершения работы, как если бы stop() был вызван явно, но это происходит, когда контекст закрывается. Обратный вызов "refresh", с другой стороны, включает еще одну функцию компонентов SmartLifecycle. Когда контекст обновляется (после того, как все объекты были созданы и инициализированы), вызывается этот обратный вызов. В этот момент процессор жизненного цикла по умолчанию проверяет логическое значение, возвращаемое методом isAutoStartup() каждого объекта SmartLifecycle. Если true, этот объект запускается в этой точке, а не ожидает явного вызова контекста или его собственного метода start() (в отличие от обновления контекста, запуск контекста не происходит автоматически при реализации стандартного контекста). Значение фазы и любые зависимости "зависит от" определяют порядок запуска, как описано выше.


Читайте также:


Комментарии

Популярные сообщения из этого блога

Методы класса Object в Java

Как получить текущий timestamp в Java

Основные опции JVM для повышения производительности и отладки