Изучаем Java EE 7 - [29]

Шрифт
Интервал


Листинг 2.34. Декоратор, преобразующий восьмизначный номер в тринадцатизначный

>@Decorator

>public class FromEightToThirteenDigitsDecorator implements NumberGenerator {

>··@Inject @Delegate

>··private NumberGenerator numberGenerator;

>··public String generateNumber() {

>····String issn = numberGenerator.generateNumber();

>····String isbn = "13-84356" + issn.substring(1);

>····returnisbn;

>··}

>}

Декораторы должны иметь точку внедрения делегата (аннотированную @Delegate) такого же типа, как и компоненты, которые они декорируют (здесь интерфейс NumberGenerator). Это позволяет объекту вызывать объект-делегат (например, целевой компонент IssnNumberGenerator), а затем, в свою очередь, вызывать на него любой бизнес-метод (например, numberGenerator.generateNumber() в листинге 2.34).

По умолчанию все декораторы отключены, как и альтернативы с перехватчиками. Декораторы необходимо активизировать в файле beans.xml, как показано в листинге 2.35.


Листинг 2.35. Активизация декоратора в дескрипторе развертывания beans.xml

>

>·············xmlns: xsi="http://www.w3.org/2001/XMLSchema-instance"

>·············xsi: schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 

>··································http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"

>·············version="1.1" bean-discovery-mode="all">

>··

>····org.agoncal.book.javaee7.chapter02.FromEightToThirteenDigitsDecorator

>··

>

Если в приложении присутствуют и перехватчики, и декораторы, то перехватчики вызываются в первую очередь.

События

Внедрение зависимостей, перехватчики и декораторы гарантируют слабую связанность, обеспечивая разнообразные варианты дополнительного поведения как во время развертывания, так и во время выполнения. События, кроме того, позволяют компонентам взаимодействовать вне зависимости от времени компиляции. Один компонент может определить событие, другой — инициировать событие, а третий — обработать его. Эта базовая схема следует шаблону проектирования «Наблюдатель» (Observer), разработанному группой Gang of Four.

Производители событий запускают события, используя интерфейс javax.enterprise.event. Производитель инициирует события вызовом метода fire(), передает объект события и не зависит от наблюдателя. В листинге 2.36 BookService запускает событие (bookAddedEvent) каждый раз при создании книги. Код bookAddedEvent.fire(book) инициирует событие и оповещает любые методы наблюдателя, следящие за этим конкретным событием. Содержание этого события — сам объект Book, который будет передан от производителя потребителю.


Листинг 2.36. BookService запускает событие каждый раз, когда создается книга

>public class BookService {

>··@Inject

>··private NumberGenerator numberGenerator;

>··@Inject

>··private Event bookAddedEvent;

>··public Book createBook(String title, Float price, String description) {

>····Book book = new Book(title, price, description);

>····book.setIsbn(numberGenerator.generateNumber());

>····bookAddedEvent.fire(book);

>····return book;

>··}

>}

События инициируются производителем событий и на них подписываются наблюдатели. Наблюдатель — это компонент с одним или несколькими «отслеживающими» методами. Каждый из этих методов наблюдателя берет в качестве параметра событие определенного типа, сопровождаемое аннотацией @Observers и опциональными квалификаторами. Метод наблюдателя оповещается о событии, если объект события соответствует типу и всем квалификаторам. В листинге 2.37 показана служба инвентаризации, задача которой — отслеживать новые книжные поступления, дополняя информацию о книжном фонде. Там используется метод addBook, который наблюдает за каждым событием с типом Book. Аннотированный параметр называется параметром события. Поэтому, как только событие инициируется компонентом BookService, контейнер CDI приостанавливает выполнение и передает событие любому зарегистрированному наблюдателю. В нашем случае в листинге 2.37 будет вызван метод addBook, который обновит список книг, а затем контейнер продолжит выполнение кода с того места, где он остановился в компоненте BookService. Это означает, что события в CDI не рассматриваются асинхронно.


Листинг 2.37. InventoryService наблюдает за событием Book

>public class InventoryService {

>··@Inject

>··private Logger logger;

>··List inventory = new ArrayList<>();

>··public void addBook(@Observes Book book) {

>····logger.info("Adding book " + book.getTitle() + "to inventory");

>····inventory.add(book);

>··}

>}

Как и большинство CDI, производство события и подписка являются типобезопасными и позволяют квалификаторам определять, какие наблюдатели событий будут использоваться. Событию может быть назначен один или несколько квалификаторов (с членами либо без таковых), которые позволяют наблюдателям отличить его от остальных событий такого же типа. Листинг 2.38 возвращается к компоненту BookService, добавив туда дополнительное событие. При создании книги инициируется событие bookAddedEvent, а при удалении — событие bookRemovedEvent, оба с типом Book. Чтобы можно было отличать эти события, каждое из них сопровождается аннотацией @Added или @Removed. Код этих квалификаторов идентичен коду в листинге 2.7: аннотация без членов и аннотированная @Qualifier.


Рекомендуем почитать
Pro Git

Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.


Java 7

Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.


MFC и OpenGL

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


Симуляция частичной специализации

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


Обработка событий в С++

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


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.