Читаем Изучаем Java EE 7 полностью

Однако существует правило, что вы можете иметь только одну точку внедрения конструктора. Именно контейнер (а не вы) выполняет внедрение, так как вы не можете вызвать конструктор в управляемой среде. Поэтому для того, чтобы контейнер мог выполнить свою работу и внедрить правильные ссылки, разрешается только один конструктор компонентов.

Другой вариант — использовать внедрение сеттера, что выглядит как внедрение конструктора. Вам просто нужно добавить к сеттеру аннотацию @Inject:

@Inject

public void setNumberGenerator(NumberGenerator numberGenerator) {

··this.numberGenerator = numberGenerator;

}

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

Внедрение по умолчанию

Предположим, NumberGenerator имеет только одну реализацию (IsbnGenearator). Тогда CDI сможет внедрить его, просто самостоятельно используя аннотацию @Inject:

@Inject

private NumberGenerator numberGenerator;

Это называется внедрением по умолчанию. Каждый раз, когда компонент или точка внедрения не объявляет очевидным образом квалификатор, контейнер по умолчанию использует квалификатор @javax.enterprise.inject.Default. На самом деле предыдущему отрывку кода идентичен следующий:

@Inject @Default

private NumberGenerator numberGenerator;

@Default — это встроенный квалификатор, сообщающий CDI, когда нужно внедрить реализацию компонента по умолчанию. Если вы определите компонент без квалификатора, ему автоматически присвоится квалификатор @Default. Таким образом, код в листинге 2.6 идентичен коду в листинге 2.5.

Листинг 2.6. Компонент IsbnGenerator с квалификатором @Default

@Default

public class IsbnGenerator implements NumberGenerator {

··public String generateNumber() {

····return "13-84356-" + Math.abs(new Random(). nextInt());

··}

}

Если у вас есть только одна реализация компонента для внедрения, применяется поведение по умолчанию, а реализация будет внедрена непосредственно с использованием @Inject. Схема класса на рис. 2.4 показывает реализацию @Default (IsbnGenerator), а также точку внедрения по умолчанию (@Inject @Default). Но иногда приходится выбирать между несколькими реализациями. Это как раз тот случай, когда нужно использовать квалификаторы.

Рис. 2.4. Схема класса с квалификатором @Default

Квалификаторы

Во время инициализации системы контейнер должен подтвердить, что каждой точке внедрения соответствует строго один компонент. Это означает, что при отсутствии доступной реализации NumberGenerator контейнер сообщит вам о неудовлетворенной зависимости и не будет развертывать приложение. При наличии только одной реализации внедрение будет работать, используя квалификатор @Default (см. рис. 2.4). Если бы в наличии имелось несколько реализаций по умолчанию, то контейнер проинформировал бы вас о неоднозначной зависимости и не стал бы развертывать приложение. Это происходит потому, что в работе типобезопасного алгоритма разрешения происходит сбой, когда контейнер не может определить строго один компонент для внедрения.

Итак, как же компонент выбирает, какая реализация (IsbnGenrator или IssnGenerator) будет внедряться? При объявлении и внедрении компонентов в большинстве фреймворков активно задействуется XML-код. CDI использует квалификаторы: в основном это аннотации Java, осуществляющие типобезопасное внедрение и однозначно определяющие тип без необходимости отката к строковым именам.

Предположим, у нас есть приложение с сервисом BookService, который создает книги с тринадцатизначным номером ISBN, и с LegacyBookService, создающим книги с восьмизначным номером ISSN. Как вы можете видеть на рис. 2.5, оба сервиса внедряют ссылку на один интерфейс NumberGenerator. Сервисы различаются реализациями благодаря использованию квалификаторов.

Рис. 2.5. Сервисы, использующие квалификаторы для однозначного внедрения

Квалификатор представляет определенную семантику, ассоциированную с типом и удовлетворяющую отдельной реализации этого типа. Это аннотация, которая определяется пользователем и, в свою очередь, сопровождается аннотацией @javax.inject.Qualifer. Например, мы можем использовать квалификаторы для замещения тринадцати- и восьмизначных генераторов чисел. Оба примера показаны в листингах 2.7 и 2.8.

Листинг 2.7. Тринадцатизначный квалификатор

@Qualifier

@Retention(RUNTIME)

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных