Выбрать главу

• перехватчики, действующие на уровне конструктора, — перехватчик, ассоциированный с конструктором целевого класса (@AroundConstruct);

• перехватчики, действующие на уровне метода, — перехватчик, ассоциированный со специальным бизнес-методом (@AroundInvoke);

• перехватчики методов задержки — перехватчик, помеченный аннотацией @AroundTimeout, вмешивается в работу методов задержки (применяется только со службой времени EJB, см. главу 8);

• перехватчики обратного вызова жизненного цикла — перехватчик, который вмешивается в работу обратных вызовов событий жизненного цикла целевого экземпляра (@PostConstruct и @PreDestroy).

Примечание

Начиная с Java EE 6, перехватчики оформились в отдельную спецификацию (до этого они входили в состав спецификации EJB). Они могут применяться к управляемым компонентам, как вы увидите далее в этом разделе, а также к компонентам EJB и веб-службам SOAP и RESTful.

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

Существует несколько способов определения перехвата. Самый простой — добавить перехватчики (уровня метода, тайм-аута или жизненного цикла) к самому компоненту, как показано в листинге 2.23. Класс CustomerService сопровождает logMethod() аннотацией @AroundInvoke. Этот метод используется для регистрации сообщения во время входа в метод и выхода из него. Как только этот управляемый компонент развертывается, любой клиентский вызов createCustomer() или findCustomerById() будет перехватываться и начнет применяться logMethod(). Обратите внимание, что область видимости этого перехватчика ограничена самим компонентом (целевым классом).

Листинг 2.23. Класс CustomerService, использующий перехватчик, предшествующий вызову

@Transactional

public class CustomerService {

··@Inject

··private EntityManager em;

··@Inject

··private Logger logger;

··public void createCustomer(Customer customer) {

····em.persist(customer);

··}

··public Customer findCustomerById(Long id) {

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

··}

··@AroundInvoke

··private 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());

····}

··}

}

Несмотря на аннотацию @AroundInvoke, logMethod() должен иметь следующий образец подписи:

@AroundInvoke

Object <METHOD>(InvocationContext ic) throws Exception;

Следующие правила относятся к методу, предшествующему вызову (а также конструктору, времени задержки или перехватчикам жизненного цикла):

• метод может иметь доступ public, private, protected либо доступ на уровне пакета, но не должно быть доступа static или final;

• метод должен иметь параметр javax.interceptor.InvocationContext и возвращать объект, который является результатом вызванного метода проб;

• метод может генерировать проверяемое исключение.

Объект InvocationContext позволяет перехватчикам контролировать поведение цепочки вызовов. Если несколько перехватчиков соединены в цепочку, то один и тот же экземпляр InvocationContext передается каждому перехватчику, который может добавить контекстуальные данные для обработки другими перехватчиками. Таблица 2.4 описывает API InvocationContext.

Таблица 2.4. Определение интерфейса InvocationContext
Метод Описание
getContextData Позволяет значениям передаваться между методами перехвата в том же экземпляре InvocationContext с использованием Map
getConstructor Возвращает конструктор целевого класса, для которого был вызван перехватчик
getMethod Возвращает метод класса компонентов, для которого был вызван перехватчик
getParameters Возвращает параметры, которые будут использоваться для вызова бизнес-метода
getTarget Возвращает экземпляр компонента, к которому относится перехватываемый метод
getTimer Возвращает таймер, ассоциированный с методом @Timeout
proceed Обеспечивает вызов следующего метода перехватчика по цепочке. Он возвращает результат следующего вызываемого метода. Если метод относится к типу void, то proceed возвращает null
setParameters Модифицирует значение параметров, используемых для вызова методов целевого класса. Типы и количество параметров должны совпадать с подписью метода компонента, иначе будет сгенерировано исключение IllegalArgumentException