Spring ApplicationListener не получает события

У меня есть следующий ApplicationListener:

package org.mycompany.listeners;

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextStartedEvent;

public class MyApplicationListener implements ApplicationListener<ContextStartedEvent> {

  public MyApplicationListener() {
    super();
    System.out.println("Application context listener is created!");
  }

  /**
   * {@inheritDoc}
   */
  public void onApplicationEvent(final ContextStartedEvent event) {
    System.out.println("Context '" + event.getApplicationContext().getDisplayName() + "' is started!");
  }

}

И следующее определение компонента:

<bean name="myApplicationListener" class="org.mycompany.listeners.MyApplicationListener" />

Я вижу, что bean-компонент создается, когда печатается сообщение из конструктора, но событие запуска контекста никогда не получается. Что мне не хватает?


person Andrey Adamovich    schedule 20.04.2011    source источник
comment
Должна ли она иметь аннотацию @Component?   -  person borjab    schedule 05.06.2014


Ответы (3)


ContextStartedEvent публикуется, когда вы явно вызываете ConfigurableApplicationContext.start() в контексте. Если вам нужно событие, которое публикуется при инициализации контекста, используйте ContextRefreshedEvent.

См. также:

person axtavt    schedule 20.04.2011
comment
Обратите внимание, что ContextRefreshedEvent может быть опубликован более одного раза, и поэтому он также может быть опубликован до инициализации всех bean-компонентов (например, при использовании CXF 2.4.2...). Однако в наиболее распространенных настройках ContextRefreshedEvent действительно будет опубликовано только после завершения контекстного запуска. - person Piotr Findeisen; 29.02.2012
comment
очень полезно, но эти соглашения выглядят неуместно :( - person Sagar balai; 28.09.2018

Поскольку у вас нет отложенных загруженных bean-компонентов (по вашему мнению), вы, скорее всего, используете события по неправильной причине и, вероятно, должны использовать что-то вроде InitializingBean вместо этого:

public class MyBean implements InitializingBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        // ...
    }

}

Из весеннего руководства:

Чтобы взаимодействовать с контейнером, управляющим жизненным циклом компонента, вы можете реализовать интерфейсы Spring InitializingBean и DisposableBean. Контейнер вызывает afterPropertiesSet() для первого и destroy() для второго, чтобы позволить bean-компоненту выполнять определенные действия при инициализации и уничтожении ваших bean-компонентов. Вы также можете добиться такой же интеграции с контейнером, не связывая свои классы с интерфейсами Spring, используя метаданные определения объекта метода init-method и метода уничтожения.

Источник: Spring Framework — жизненный цикл обратные вызовы

person Mike Minicki    schedule 28.11.2012
comment
Я думаю, что метод afterPropertiesSet применяется к одному компоненту, а не ко всему контексту приложения Spring. docs.spring.io/ весна/документы/2.5.6/api/org/springframework/beans/ - person Alina Danila; 04.11.2013

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

person qwerty    schedule 20.04.2011
comment
В моем контексте нет bean-компонентов с ленивой инициализацией. - person Andrey Adamovich; 20.04.2011