Как запустить демон при запуске сервера в spring

Я хочу запустить поток почтовой службы демона при запуске сервера tomcat. Итак, я аннотировал метод с аннотацией @Async.

У меня есть класс, который реализует интерфейс ApplicationListener. Когда я вызываю свой асинхронный метод из этого класса, он никогда не запускается асинхронно и блокирует текущий поток. И когда я вызываю свой метод async из класса контроллера spring, он никогда не блокирует и не запускается асинхронно.

Почему метод async успешно выполняется из одного класса, а не из другого класса?

Что я делаю неправильно, и как я могу выполнить мой метод асинхронизации при запуске сервера?

Спасибо заранее.

Изменить: Привет, ребята, я попытался использовать интерфейс InitializingBean, @PostConstruct, метод init-метода для вызова моего метода async, но он никогда не выполнялся. Затем я понял, что мой lazy-init по умолчанию - true, поэтому я делаю lazy-init ложным для своего InitializingBean. Теперь он выполняет мой метод asnyc, но он блокирует текущий поток, и теперь еще одна проблема, с которой я столкнулся, заключается в том, что мой сервер не останавливался изящно, но я должен остановить мой сервер.

Ответ 1

Прежде всего вам не нужно реализовывать интерфейс ApplicationListener. Вы работаете с Spring - достаточно контекста приложения.

Во-вторых, вы говорите о Spring @Async, это означает, что ваша задача должна быть запущена из контекста приложения, а контроллер bean является его частью.

Вы должны убедиться, что у вас <annotation-driven> в вашем Spring xml файле.

Вы можете запустить свою задачу в функции @PostConstruct:

@Component
public class SampleBeanImpl implements SampleBean {

  @Async
  void doSomething() { … }
}


@Component
public class SampleBeanInititalizer {

  @Autowired
  private final SampleBean bean;

  @PostConstruct
  public void initialize() {
    bean.doSomething();
  }
}

Ответ 2

Основываясь на Spring reference, использование @Async имеет ограничения при запуске приложения:

@Async не может использоваться в сочетании с обратными вызовами жизненного цикла, такими как @PostConstruct. Для асинхронной инициализации Spring beans в настоящее время должны использовать отдельную инициализацию Spring bean, которая вызывает @Async аннотированный метод для целевого объекта.

Итак, в вашем случае, может быть, было бы хорошо иметь реализацию InitializingBean с вашей целевой bean, а затем запустить через этот демон.

Ответ 3

Добавили ли тэг <annotation-driven> в свой контекст приложения? Из справочного документа Spring:

Чтобы включить аннотации @Scheduled и @Async, просто добавьте элемент, управляемый аннотацией, из пространства имен задач в вашей конфигурации.

Обратите внимание, что вы также должны сконфигурировать экземпляр исполнителя. Из определение схемы задач:

Определяет экземпляр ThreadPoolTaskExecutor с настраиваемыми размерами пула, размерами очереди, сохранением и отклонениями. См. Javadoc для аннотации org.springframework.scheduling.annotation.EnableAsync для получения информации о альтернативах на основе кода для этого элемента XML.

Итак, чтобы создать исполнителя, резервное копирование которого осуществляется пулом потоков с 5 потоками, вы должны сделать следующее:

<task:annotation-driven executor="myExecutor"/>
<task:executor id="myExecutor" pool-size="5"/>

Дополнительные параметры конфигурации см. в @EnableAsync javadoc, как указано выше.

Ответ 4

мой английский - это пул. вы должны установить Service Class @Lazy (false).

Ответ 5

@asyn является частью структуры spring, используется ли ваш слушатель в контексте spring? Если нет, я предлагаю начать новый поток в вашем асинхронном методе.