Spring Завершение загрузки

Как я могу зарегистрировать/добавить обычную процедуру отключения, которая будет срабатывать, когда мое приложение загрузки Spring отключится?

Сценарий: я развертываю приложение Spring для загрузки в контейнер сервлетов Jetty (т.е. нет встроенного Jetty). В моем приложении используется Logback для ведения журнала, и я хочу изменить уровни ведения журнала во время выполнения, используя конфигуратор Logback MBean JMX. В его документации указано, что во избежание утечек памяти при выключениях должен быть вызван определенный метод выключения LoggerContext.

Каковы хорошие способы прослушивания Spring событий завершения загрузки?

Я пробовал:

public static void main(String[] args) throws Exception {
    ConfigurableApplicationContext cac = SpringApplication.run(Example.class, args);

    cac.addApplicationListener(new ApplicationListener<ContextClosedEvent>() {

        @Override
        public void onApplicationEvent(ContextClosedEvent event) {
            logger.info("Do something");
        }
    });
}

но этот зарегистрированный прослушиватель не вызывается, когда приложение отключается.

Ответ 1

http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-application-exit

Каждое SpringApplication регистрирует крюк остановки с помощью JVM, чтобы гарантировать, что ApplicationContext будет закрыт грациозно при выходе. Можно использовать все стандартные обратные вызовы Spring (например, интерфейс DisposableBean или аннотация @PreDestroy).

Кроме того, beans может реализовать интерфейс org.springframework.boot.ExitCodeGenerator, если они хотят вернуть конкретный код выхода при завершении приложения.

Ответ 2

Ваш слушатель зарегистрирован слишком поздно (эта строка никогда не будет достигнута, пока контекст не будет закрыт). Достаточно сделать это @Bean.

Ответ 3

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {

    public static void main(
            String[] args) {
        SpringApplication.run(Application.class,
                              args);
    }

    @NotNull
    @Bean
    ServletListenerRegistrationBean<ServletContextListener> myServletListener() {
        ServletListenerRegistrationBean<ServletContextListener> srb =
                new ServletListenerRegistrationBean<>();
        srb.setListener(new ExampleServletContextListener());
        return srb;
    }
}

 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;

 public class ExampleServletContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(
        ServletContextEvent sce) {
    // Context Initialised
    }

    @Override
    public void contextDestroyed(
        ServletContextEvent sce) {
       // Here - what you want to do that context shutdown    
   }

}