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

Начиная с Spring 4.2, вы можете зарегистрировать прослушиватель событий для любого общедоступного метода управляемого bean-компонента с помощью аннотации @EventListener. BlockedListNotifier можно переписать следующим образом:

Java

public class BlockedListNotifier {

    private String notificationAddress;

    public void setNotificationAddress(String notificationAddress) {
        this.notificationAddress = notificationAddress;
    }

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

Kotlin

class BlockedListNotifier {

    lateinit var notificationAddress: String

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

Сигнатура метода еще раз объявляет тип события, которое он слушает, но на этот раз с гибким именем и без реализации определенного интерфейса слушателя. Тип события также можно сузить с помощью универсальных шаблонов, если фактический тип события разрешает ваш универсальный параметр в его иерархии реализации.

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

Java

@EventListener({ContextStartedEvent.class, ContextRefreshedEvent.class})
public void handleContextStart() {
    // ...
}

Kotlin

@EventListener(ContextStartedEvent::class, ContextRefreshedEvent::class)
fun handleContextStart() {
    // ...
}

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

В следующем примере показано, как наш уведомитель может быть переписан для вызова только в том случае, если атрибут содержимого события равен my-event:

Java

@EventListener(condition = "#blEvent.content == 'my-event'")
public void processBlockedListEvent(BlockedListEvent blockedListEvent) {
    // уведомляем соответствующие стороны через notificationAddress...
}

Kotlin

@EventListener(condition = "#blEvent.content == 'my-event'")
fun processBlockedListEvent(blockedListEvent: BlockedListEvent) {
    // уведомляем соответствующие стороны через notificationAddress...
}

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

Название Расположение Описание Пример
Событие (Event)
корневой объект
Фактический ApplicationEvent #root.event или event
Массив аргументов
корневой объект
Аргументы (в виде массива объектов), используемые для вызова метода. #root.args или args; args[0] для доступа к первому аргументу и т. д.
Имя аргумента
контекст оценки
Имя любого из аргументов метода. Если по какой-то причине имена недоступны (например, потому что в скомпилированном байтовом коде нет отладочной информации), отдельные аргументы также доступны с использованием синтаксиса #a<#arg>, где <#arg> означает индекс аргумента (начиная с 0). #blEvent или #a0 (вы также можете использовать обозначение параметра #p0 или #p<#arg> в качестве псевдонима)

Обратите внимание, что #root.event дает вам доступ к базовому событию, даже если ваша сигнатура метода фактически ссылается на произвольный опубликованный объект.

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

Java

@EventListener
public ListUpdateEvent handleBlockedListEvent(BlockedListEvent event) {
    // уведомляем соответствующие стороны через notificationAddress и
    // затем публикуем событие ListUpdateEvent...
}

Kotlin

@EventListener
fun handleBlockedListEvent(event: BlockedListEvent): ListUpdateEvent {
    // уведомляем соответствующие стороны через notificationAddress и
    // затем публикуем событие ListUpdateEvent...
}

Эта функция не поддерживается для асинхронных слушателей.

Этот новый метод публикует новое событие ListUpdateEvent для каждого события BlockedListEvent, обработанного указанным выше методом. Если вам нужно опубликовать несколько событий, вы можете вместо этого вернуть коллекцию событий.


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


Комментарии

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

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

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

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