Spring IoC контейнер: дополнительные возможности ApplicationContext, асинхронные слушатели, упорядочивание слушателей

Асинхронные слушатели

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

Java

@EventListener
@Async
public void processBlockedListEvent(BlockedListEvent event) {
    // BlockedListEvent обрабатывается в отдельном потоке
}

Kotlin

@EventListener
@Async
fun processBlockedListEvent(event: BlockedListEvent) {
    // BlockedListEvent обрабатывается в отдельном потоке
}

Помните о следующих ограничениях при использовании асинхронных событий:

  • Если асинхронный прослушиватель событий выдает исключение, оно не передается вызывающей стороне.
  • Методы асинхронного прослушивателя событий не могут публиковать последующее событие, возвращая значение. Если вам нужно опубликовать другое событие в результате обработки, введите ApplicationEventPublisher, чтобы опубликовать событие вручную.

Упорядочивание слушателей

Если вам нужно, чтобы один слушатель вызывался перед другим, вы можете добавить аннотацию @Order к объявлению метода, как показано в следующем примере:

Java

@EventListener
@Order(42)
public void processBlockedListEvent(BlockedListEvent event) {
    // уведомляем соответствующие стороны через notificationAddress...
}

Kotlin

@EventListener
@Order(42)
fun processBlockedListEvent(event: BlockedListEvent) {
    // уведомляем соответствующие стороны через notificationAddress...
}

Общие события

Вы также можете использовать универсальные шаблоны для дальнейшего определения структуры вашего события. Рассмотрите возможность использования EntityCreatedEvent<T>, где T - тип фактического созданного объекта. Например, вы можете создать следующее определение прослушивателя, чтобы получать только EntityCreatedEvent для Person:

Java

@EventListener
public void onPersonCreated(EntityCreatedEvent<Person> event) {
    // ...
}

Kotlin

@EventListener
fun onPersonCreated(event: EntityCreatedEvent<Person>) {
    // ...
}

Из-за стирания типа это работает только в том случае, если запускаемое событие разрешает общие параметры, по которым фильтруется прослушиватель событий (то есть что-то вроде class PersonCreatedEvent extends EntityCreatedEvent<Person> { … }).

В определенных обстоятельствах это может стать довольно утомительным, если все события следуют одной и той же структуре (как и должно быть в случае события в предыдущем примере). В таком случае вы можете реализовать ResolvableTypeProvider, чтобы направить структуру за пределы того, что предоставляет среда выполнения. Следующее событие показывает, как это сделать:

Java

public class EntityCreatedEvent<T> extends ApplicationEvent implements ResolvableTypeProvider {

    public EntityCreatedEvent(T entity) {
        super(entity);
    }

    @Override
    public ResolvableType getResolvableType() {
        return ResolvableType.forClassWithGenerics(getClass(), ResolvableType.forInstance(getSource()));
    }
}

Kotlin

class EntityCreatedEvent<T>(entity: T) : ApplicationEvent(entity), ResolvableTypeProvider {

    override fun getResolvableType(): ResolvableType? {
        return ResolvableType.forClassWithGenerics(javaClass, ResolvableType.forInstance(getSource()))
    }
}

Это работает не только с ApplicationEvent, но и с любым произвольным объектом, который вы отправляете как событие.


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


Комментарии

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

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

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

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