private NumberGenerator numberGenerator;
У вас может быть несколько файлов beans.xml, объявляющих несколько альтернатив, в зависимости от вашей среды (разработка, поддержка готового приложения, тестирование и т. д.).
Производители данных
Я показал вам, как внедрять одни компоненты CDI в другие. Благодаря производителям данных вы также можете внедрять примитивы (такие как int, long, float и т. д.), массивы и любой POJO, не поддерживающий CDI. Под поддержкой CDI я имею в виду любой класс, упакованный в архив, содержащий файл beans.xml.
По умолчанию вы не можете внедрять такие классы, как java.util.Date или java.lang.String. Так происходит потому, что все эти классы упакованы в файл rt.jar (классы среды исполнения Java), а этот архив не содержит дескриптор развертывания beans.xml. Если в архиве в папке META-INF нет файла beans.xml, CDI не инициирует обнаружение компонента и POJO не будут обрабатываться как компоненты, а значит, и внедряться. Единственный способ внедрения POJO состоит в использовании полей и методов производителей данных, как показано в листинге 2.16.
public class NumberProducer {
··@Produces @ThirteenDigits
··private String prefix13digits = "13-";
··@Produces @ThirteenDigits
··private int editorNumber = 84356;
··@Produces @Random
··public double random() {
····return Math.abs(new Random(). nextInt());
··}
}
Класс NumberProducer в листинге 2.16 имеет несколько атрибутов и методов (все с аннотацией javax.enterprise.inject.Produces). Это означает, что все произведенные типы и классы теперь могут внедряться с помощью @Inject с использованием квалификатора (@ThirteenDigits, @EightDigits или @Random).
Метод производителя данных (random() в листинге 2.16) — это метод, выступающий в качестве фабрики экземпляров компонентов. Он позволяет внедряться возвращаемому значению. Мы даже можем указать квалификатор (например, @Random), область видимости и EL-имя, как вы увидите позднее. Поле производителя данных (prefix13digits и editorNumber) — более простая альтернатива методу производителя данных, не имеющая бизнес-кода. Это только свойство, которое становится внедряемым.
В листинге 2.9 IsbnGenerator генерирует номер ISBN с формулой "13-84356-" + Math.abs(newRandom(). nextInt()). С помощью NumberProducer (см. листинг 2.16) мы можем использовать произведенные типы для изменения этой формулы. В листинге 2.17 IsbnGenerator теперь внедряет и строку, и целое число с аннотациями @Inject @ThirteenDigits, представляющими префикс ("13-") и идентификатор редактора (84356) номера ISBN. Случайный номер внедряется с помощью аннотаций @Inject @Random и возвращает число с двойной точностью.
@ThirteenDigits
public class IsbnGenerator implements NumberGenerator {
··@Inject @ThirteenDigits
··private String prefix;
··@Inject @ThirteenDigits
··private int editorNumber;
··@Inject @Random
··private double postfix;
··public String generateNumber() {
····returnprefix + editorNumber + postfix;
··}
}
В листинге 2.17 вы можете видеть строгую типизацию в действии. Благодаря тому же синтаксису (@Inject @ThirteenDigits) CDI знает, что ему нужно внедрить строку, целое число или реализацию NumberGenerator. Преимущество применения внедряемых типов (см. листинг 2.17) вместо фиксированной формулы (см. листинг 2.9) для генерации чисел состоит в том, что вы можете использовать все возможности CDI, такие как альтернативы (и при необходимости иметь альтернативный алгоритм генератора номеров ISBN).
InjectionPoint API. В листинге 2.16 атрибуты и возвращаемое значение, полученное посредством @Produces, не требуют никакой информации о том, куда они внедряются. Но в определенных случаях объектам нужна информация о точке их внедрения. Это может быть способ конфигурации или изменения поведения в зависимости от точки внедрения.
Например, рассмотрим создание автоматического журнала. В JDK для создания java.util.logging.Logger вам необходимо задать категорию класса, владеющего им. Скажем, если вам нужен автоматический журнал для BookService, следует написать:
Logger log = Logger.getLogger(BookService.class.getName());