Все эти возможности предоставляются с сохранением безопасности типов. CDI никогда не полагается на строковые идентификаторы, чтобы определить, насколько подходят друг другу объекты. Вместо этого для скрепления компонентов CDI использует строго типизированные аннотации (например, связки квалификаторов, стереотипов и перехватчиков). Применение дескрипторов XML минимизировано до информации, связанной непосредственно с развертыванием.
Почти каждая спецификация Java EE содержит опциональный дескриптор развертывания XML. Обычно он описывает, как компонент, модуль или приложение (например, корпоративное или веб-приложение) должны быть сконфигурированы. При использовании CDI дескриптор развертывания называется beans.xml и является обязательным. Он может применяться для конфигурирования определенного функционала (перехватчиков, декораторов, альтернатив и т. д.), но для этого необходимо активизировать CDI. Это требуется для того, чтобы CDI идентифицировал компоненты в вашем пути к классу (так называемое обнаружение компонентов).
Чудо происходит как раз на этапе обнаружения компонентов: в тот момент, когда CDI преобразует объекты POJO в компоненты CDI. Во время развертывания CDI проверяет все JAR- и WAR-файлы вашего приложения и каждый раз, когда находит дескриптор развертывания beans.xml, управляет всеми объектами POJO, которые впоследствии становятся компонентами CDI. Без файла beans.xml в пути к классу (в каталоге META-INF или WEB-INF) CDI не сможет использовать внедрение, перехват, декорацию и т. д. Без этой разметки файл CDI не будет работать. Если ваше веб-приложение содержит несколько файлов JAR и вы хотите активизировать CDI применительно ко всему приложению, то каждому файлу JAR потребуется отдельный файл beans.xml для инициирования CDI и обнаружения компонентов.
Обзор спецификаций по CDI
CDI стал общим основанием для нескольких спецификаций Java EE. Одни спецификации в большой степени полагаются на него (Bean Validation, JAX-RS), другие посодействовали его возникновению (EJB), а третьи связаны с ним (JSF). CDI 1.1 затрагивает несколько спецификаций, но является неполным без остальных: Dependency Injection for Java 1.0 (запрос JSR 330), Managed Bean 1.0 (запрос JSR 342), Common Annotations 1.2 (запрос JSR 250), Expression Language 3.0 (запрос JSR 341) и Interceptors 1.2 (запрос JSR 318).
Краткая история спецификаций CDI
В 2006 году Гевин Кинг (создатель Seam), вдохновленный идеями фреймворков Seam, Guise и Spring, возглавил работу над спецификацией по запросу JSR 299, позднее названной Web Beans (Веб-компоненты). Поскольку она создавалась для Java EE 6, ее пришлось переименовать в Context and Dependency Injection 1.0. При этом за основу был взят новый запрос JSR 330: Dependency Injection for Java 1.0 (также известный как @Inject).
Эти две спецификации взаимно дополняли друг друга и не могли использоваться в Java EE по отдельности. Внедрение зависимостей для Java определяло набор аннотаций (@Inject, @Named, @Qualifier, @Scope и @Singleton), используемых преимущественно для внедрения. CDI дал семантику запросу JSR 330 и добавил еще больше новых возможностей, таких как управление контекстом, события, декораторы и улучшенные перехватчики (запрос JSR 318). Более того, CDI позволил разработчику расширить платформу в рамках стандарта, что ранее не представлялось возможным. Целью CDI было заполнить все пробелы, а именно:
• придать платформе большую целостность;
• соединить веб-уровень и уровень транзакций;
• сделать внедрение зависимостей полноправным компонентом платформы;
• иметь возможность легко добавлять новые расширения.
Сегодня, с появлением Java EE 7, CDI 1.1 становится основанием для многих запросов JSR, и здесь уже появились определенные улучшения.
В CDI 1.1 не добавилось никаких важных функций. Вместо этого новая версия концентрируется на интеграции CDI с другими спецификациями, например, благодаря активному использованию перехватчиков, добавлению диалогов в запрос сервлета либо обогащению событий жизненного цикла приложения в Java EE. Ниже перечислены новые возможности, реализованные в CDI 1.1:
• новый класс CDI обеспечивает программный доступ к средствам CDI извне управляемого компонента;
• перехватчики, декораторы и альтернативы могут быть приоритизированы (@Priority) и упорядочены для всего приложения;
• при добавлении аннотации @Vetoed к любому типу или пакету CDI перестает считать данный тип или пакет своим компонентом;
• квалификатор @New в CDI 1.1 считается устаревшим, и сегодня приложениям предлагается вместо этого внедрять ограниченные компоненты @Dependent;
Читать дальше