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

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

Перехватчики классов

Листинг 2.23 определяет перехватчик, доступный только для CustomerService. Но чаще всего вам требуется изолировать сквозную функциональность в отдельный класс и сообщить контейнеру, чтобы он перехватил вызовы нескольких компонентов. Запись информации в журнал (логирование) — типичный пример ситуации, когда вам требуется, чтобы все методы всех ваших компонентов регистрировали сообщения о входе и выходе. Для указания перехватчика класса вам необходимо разработать отдельный класс и дать контейнеру команду применить его на определенном компоненте или методе компонента.

Чтобы обеспечить совместный доступ к коду множественным компонентам, возьмем методы logMethod() из листинга 2.23 и изолируем их в отдельный класс, как показано в листинге 2.24. Обратите внимание на метод init(), который сопровождается аннотацией @AroundConstruct и будет вызван только вместе с конструктором компонента.


Листинг 2.24. Класс перехватчика с Around-Invoke и Around-Construct

>public class LoggingInterceptor {

>··@Inject

>··private Logger logger;

>··@AroundConstruct

>··private void init(InvocationContext ic) throws Exception {

>····logger.fine("Entering constructor");

>····try {

>······ic.proceed();

>····} finally {

>······logger.fine("Exiting constructor");

>····}

>··}

>··@AroundInvoke

>··public Object logMethod(InvocationContext ic) throws Exception {

>····logger.entering(ic.getTarget(). toString(), ic.getMethod(). getName());

>····try {

>······return ic.proceed();

>····} finally {

>······logger.exiting(ic.getTarget(). toString(), ic.getMethod(). getName());

>····}

>··}

>}

Теперь LoggingInterceptor может быть прозрачно обернут любым компонентом, заинтересованным в этом перехватчике. Для этого компоненту необходимо сообщить контейнеру аннотацию @javax.interceptor.Interceptors. В листинге 2.25 аннотация задается методом createCustomer(). Это означает, что любой вызов этого метода будет перехвачен контейнером, и будет вызван класс LoggingInterceptor (регистрация сообщения на входе в метод и выходе из него).


Листинг 2.25. CustomerService использует перехватчик в одном методе

>@Transactional

>public class CustomerService {

>··@Inject

>··private EntityManager em;

>··@Interceptors(LoggingInterceptor.class)

>··public void createCustomer(Customer customer) {

>····em.persist(customer);

>··}

>··public Customer findCustomerById(Long id) {

>····return em.find(Customer.class, id);

>··}

>}

В листинге 2.25 аннотация @Interceptors прикрепляется только к методу createCustomer(). Это означает, что, если клиент вызывает findCustomerById(), контейнер не будет перехватывать вызов. Если вы хотите, чтобы перехватывались вызовы обоих методов, можете добавить аннотацию @Interceptors либо сразу к обоим методам, либо к самому компоненту. Когда вы это делаете, перехватчик приводится в действие при вызове любого из методов. А поскольку перехватчик имеет аннотацию @AroundConstruct, вызов конструктора тоже будет перехвачен.

>@Transactional

>@Interceptors(LoggingInterceptor.class)

>public class CustomerService {

>··public void createCustomer(Customer customer) {…}

>··public Customer findCustomerById(Long id) {…}

>}

Если ваш компонент имеет несколько методов и вы хотите применить перехватчик ко всему компоненту за исключением определенного метода, можете использовать аннотацию javax.interceptor.ExcludeClassInterceptors для исключения перехвата вызова. В следующем отрывке кода вызов к updateCustomer() не будет перехвачен, а остальные будут:

>@Transactional

>@Interceptors(LoggingInterceptor.class)

>public class CustomerService {

>··public void createCustomer(Customer customer) {…}

>··public Customer findCustomerById(Long id) {…}

>··@ExcludeClassInterceptors

>··public Customer updateCustomer(Customer customer) {… }

>}

Перехватчик жизненного цикла

В начале этой главы я рассказывал о жизненном цикле управляемого компонента (см. рис. 2.2) и событиях обратного вызова. С помощью аннотации обратного вызова вы можете дать контейнеру команду вызвать метод в определенной фазе жизненного цикла (@PostConstruct и @PreDestroy). Например, если вы хотите вносить в журнал запись каждый раз, когда создается экземпляр компонента, вам просто нужно присоединить аннотацию @PostConstruct к методу вашего компонента и добавить к ней некоторые механизмы записи в журнал. Но что, если вам нужно перехватывать события жизненного цикла многих типов компонентов? Перехватчики жизненного цикла позволяют изолировать определенный код в отдельный класс и вызывать его, когда приводится в действие событие жизненного цикла.

Листинг 2.26 демонстрирует класс ProfileInterceptor с двумя методами: logMethod(), который используется для постконструкции, и profile(), применяемый для перехвата методов (@AroundInvoke).


Листинг 2.26. Перехватчик с жизненным циклом и Around-Invoke

>public class ProfileInterceptor {

>··@Inject

>··private Logger logger;

>··@PostConstruct

>··public void logMethod(InvocationContext ic) throws Exception {

>····logger.fine(ic.getTarget(). toString());

>····try {

>······ic.proceed();

>····} finally {

>······logger.fine(ic.getTarget(). toString());

>····}

>··}

>··@AroundInvoke

>··public Object profile(InvocationContext ic) throws Exception {


Рекомендуем почитать
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 так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.