Статьи

Взгляд на CDI 2.0 EDR1

CDI является одним из лучших дополнений к Java EE из последних. Это мнение широко распространено среди пользователей и интеграторов. Текущая версия CDI 1.2 была выпущена в апреле 2014 года. Сейчас, в середине 2015 года, нам предстоит предварительная проверка спецификации CDI 2.0. CDI 2.0 будет работать на Java 8 и выше.

Финальный релиз запланирован на 2016 год, и дорожная карта содержит несколько интересных пунктов:

  • Разделение API на две части и Java SE: Разделение API является важным шагом, поддерживающим движение микросервисов. Загрузите CDI из каждого main() всего за пару строк.
  • Асинхронные и приоритетные события позволяют управлять порядком наблюдателя событий и доставлять события асинхронно
  • JDK 8: CDI 1.x был ориентирован на Java 1.6 и выше. Java 8 позволяет многочисленные улучшения и помогает оптимизировать API CDI.
  • CDI позволяет расширение от его происхождения. SPI отлично подходит для улучшения CDI с помощью таких платформ, как DeltaSpike, Spring Data, Camel, Metrics for CDI и многих других. CDI 2.0 направлена ​​на улучшение поддержки расширений
  • Вы знали? CDI интенсивно использует AOP, чтобы обеспечить очень удобное использование. Все обычные области, такие как RequestScoped, ConversationScoped, SessionScoped и ApplicationScoped, используют прокси для поиска контекстных экземпляров. Но одно ограничение заключается в том, что CDI не допускает самоинъекций или перехватчиков при локальных вызовах методов. Пакет AOP позаботится об этих проблемах и улучшит определенные части спецификации.

Однако давайте взглянем на API CDI 2.0 EDR (предварительный обзор проекта), новый и заслуживающий внимания .

Асинхронные события

Асинхронные события — это элемент № 1 в списке пожеланий пользователей CDI. Эта проблема была поднята в начале 2011 года и является одним из основных моментов в CDI 2.0. Много горячих обсуждений было необходимо, чтобы включить асинхронные обработанные события и не нарушать существующий код путем введения асинхронности. Текущий проект требует двусторонней активации

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class AsyncEvents {
 
    @Inject
    private Event<MyEventPayload> event;
 
    public void triggerEvent() {
        event.fireAsync(new MyEventPayload());
    }
 
    public void asyncEventObserver(@ObservesAsync
                                    MyEventPayload payload) {
        System.out.println("Yay, I'm called async!");
    }
 
    public void eventObserver(@Observes MyEventPayload payload) {
        System.out.println("Yay, I'm called too. " +
                          "Other @Observes are notified in order.");
    }
 
    public static class MyEventPayload {
 
    }
}

События могут инициироваться с помощью асинхронной обработки наблюдателей с асинхронной поддержкой. Наблюдатели, использующие @Observes , также уведомляются в вызывающей ветке. Завершение асинхронных наблюдателей событий можно отслеживать с помощью CompletionStage который возвращается при вызове fireAsync .

Наблюдатели асинхронных событий могут работать с экземплярами контекстного компонента, когда активна обработка события. По умолчанию @RequestScoped областями являются @RequestScoped и @ApplicationScoped . @SessionScoped исключен по разным причинам. Просто подумайте, как вести себя, когда сеанс заканчивается в середине обработки события. Пользователи должны знать об эффектах при изменении полезной нагрузки события или данных в контекстных случаях. CDI не обеспечивает неизменности полезной нагрузки события, но настоятельно рекомендуется предотвращать условия гонки из-за параллелизма.

Контейнер CDI отвечает за обеспечение многопоточной инфраструктуры. Иногда вы хотите предоставить собственного исполнителя для контроля уровня параллелизма или обернуть асинхронные вызовы. Метод fireAsync позволяет указывать отдельных исполнителей для каждого вызова.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
private ExecutorService executor;
 
    @Inject
    private Event<MyEventPayload> event;
 
    @PostConstruct
    public void postConstruct() {
        int threads = Runtime.getRuntime().availableProcessors();
        executor = new ThreadPoolExecutor(threads, threads, 1,
             TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>());
 
    }
 
    @PreDestroy
    public void preDestroy() {
        executor.shutdown();
    }
 
    public void triggerEventWithExecutor() {
        event.fireAsync(new MyEventPayload(), executor);
    }

Приведенный выше пример создает / уничтожает исполнителя. Вы можете использовать CDI-управляемого исполнителя с методом продюсера ( @Produces ) и @Inject его везде, где вам это нужно. CDI это круто, а?

Асинхронные события останутся горячей темой, и это точно не окончательная форма.

Заказанные наблюдатели событий

Порядок уведомления при использовании наблюдателей событий непредсказуем в CDI 1.2. С 2.0 это изменится.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class PrioritizedEvents {
 
    @Inject
    private Event<MyEventPayload> event;
 
    public void trigger() {
        event.fire(new MyEventPayload());
    }
 
    public void observeBeforeOtherObservers(@Observes
                    @Priority(Interceptor.Priority.APPLICATION + 499) MyEventPayload payload) {
        System.out.println("Notified before all other observers");
    }
 
    public void observeAfterOtherObservers(@Observes
                    @Priority(Interceptor.Priority.APPLICATION + 501) MyEventPayload payload) {
        System.out.println("Notified after all other observers");
    }
 
    public static class MyEventPayload {
 
    }
}

На порядок наблюдателей событий можно влиять, применяя аннотацию @Priority . Почему влияет и не контролируется?

Ответ на этот вопрос немного длиннее, и вам необходимо понять часть CDI, касающуюся безопасного разрешения. Наблюдатели событий выбираются по типу полезной нагрузки. Наблюдатели событий могут наблюдать различные типы, интерфейсы, классы, подтипы, квалифицированные и неквалифицированные типы. Выбор наблюдателей событий происходит в тот момент, когда событие инициируется, либо с помощью Event либо API-интерфейса BeanManager . Вы можете уведомить другой набор наблюдателей событий, используя, например, тип или его подтип. Поэтому нет глобального порядка наблюдателей событий, что приводит нас к аннотации @Priority .

Применяя @Priority некоторые наблюдатели могут быть уведомлены раньше, а некоторые позже. Значением по умолчанию является Interceptor.Priority.APPLICATION + 500 что приводит к 2500 . Это значение по умолчанию для всех наблюдателей событий, которые не имеют аннотации @Priority .

@Priority рассмотрение @Priority показывает, что он применим только к типам прямо сейчас. Это будет меняться, пока CDI 2.0 не станет окончательным.

CDI JumpStart ака. CDI для Java SE

CDI для JavaSE доступен с самого начала, или, позвольте мне сказать это так: вы можете загружать Weld и OpenWebBeans в JavaSE без необходимости контейнера JavaEE. CDI 2.0 определяет только стандартный способ загрузки контейнера CDI стандартным способом. Этот предмет мой любимый.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
public class CDIJumpStart {
 
    public static void main(String[] args) {
        try(CDI<Object> cdi = CDI.getCDIProvider().initialize()) {
            cdi.select(MyApp.class).get().runMyApplication();
        }
    }
 
    private static class MyApp{
        public void runMyApplication(){
            // ...
        }
    }
}

Код запустит контейнер CDI и вызовет метод для запуска вашего приложения. Как только ваше приложение будет готово, контейнер будет закрыт с помощью шаблона try-with-resources . Код для запуска автономного и, возможно, приложения microservice-ish на две строки длиннее Spring Boot. Основным отличием от Spring или Dropwizard является экосистема, я не смог найти интеграцию для встроенного Tomcat, из коробки. Полагаю, пройдет некоторое время, пока CDI для JavaSE достигнет переломного момента, чтобы стать реальной альтернативой фреймворку для микросервиса.

Вывод

CDI 2.0 EDR является лишь небольшим результатом продолжающихся усилий JSR365. Есть много вопросов, ожидающих обсуждения и уточнения. Команда сварщиков JBoss усердно работает над развитием спецификаций и где-то в будущем придет RI. CDI является горячей темой и остается очень привлекательной — для Java EE и SE. Оставайтесь с нами и следуйте CDI 2.0

Свяжитесь с CDI Spec:

Ссылка: Посмотрите на CDI 2.0 EDR1 от нашего партнера JCG Марка Палуха в блоге paluch.biz .