Главная » Spring » Аннотирование аспектов Spring

0

Важной особенностью, появившейся в AspectJ 5, стала возмож- ность использовать аннотации для создания аспектов. До выхода версии AspectJ 5 для создания аспектов AspectJ требовалось знать синтаксис расширения языка Java. Однако появление возможно- сти использования аннотаций AspectJ свело преобразование любых классов в аспекты к простому добавлению в них нескольких анно- таций. Эту новую возможность часто называют как @AspectJ.

Взглянув еще раз на класс Audience, можно заметить, что он содер- жит всю необходимую функциональность, реализующую поведение публики в зале, но в нем отсутствует что-либо, превращающее его в аспект. По этой причине нам пришлось объявлять совет и срез множества точек сопряжения в конфигурационном XML-файле.

С помощью аннотаций @AspectJ можно превратить класс Audience в аспект, не прибегая к созданию дополнительных классов или объ- явлению компонентов. В листинге 5.6 представлен новый класс Audience, на этот раз преобразованный в аспект с помощью аннота- ций.

Листинг 5.6. Преобразование класса Audience в аспект с помощью аннотаций

package com.springinaction.springidol;

import  org.aspectj.lang.annotation.AfterReturning; import    org.aspectj.lang.annotation.AfterThrowing; import  org.aspectj.lang.annotation.Aspect;

import  org.aspectj.lang.annotation.Before; import   org.aspectj.lang.annotation.Pointcut;

@Aspect

public class Audience {

@Pointcut(                                               // Определение  среза

"execution(*  com.springinaction.springidol.Performer.perform(..))") public void performance() {

}

@Before("performance()")

public void takeSeats() {                 // Перед выступлением System.out.println("The audience is taking their seats.");

}

@Before("performance()")                 // Перед выступлением public  void  turnOffCellPhones()  {

System.out.println("The audience is turning off their cellphones");

}

@AfterReturning("performance()")       // После успешного выступления public  void  applaud()  {

System.out.println("CLAP   CLAP   CLAP   CLAP   CLAP");

}

@AfterThrowing("performance()")

public void demandRefund() {            // После неудачного выступления System.out.println("Boo!  We  want  our  money  back!");

}

}

Теперь новый класс Audience отмечен аннотацией @Aspect. Эта ан- нотация указывает, что Audience является не обычным простым Java- объектом, а аспектом.

Аннотация @Pointcut используется в @AspectJ для определения среза множества точек сопряжения. Значение параметра аннотации

@Pointcut является выражением AspectJ. Здесь выражение указывает, что аспект будет подключаться к точкам сопряжения, соответствую- щим методу perform() интерфейса Performer. Имя среза определяется именем метода, к которому применяется аннотация. То есть данный срез имеет имя performance(). Фактическое тело метода performance() не имеет значения и в действительности должно быть пустым. Сам метод служит лишь точкой подключения аннотации @Pointcut.

Все методы класса Audience отмечены аннотациями, определяю- щими советы. Аннотация @Before применяется к методам takeSeats() и turnOffCellPhones(), указывая, что эти два метода являются сове- тами, выполняемыми перед вызовом целевого метода. Аннотация

@AfterReturning указывает, что метод applaud() является советом, вы-

полняемым в случае благополучного завершения целевого метода. И аннотация @AfterThrowing перед методом demandRefund() указывает, что он будет вызываться в случае появления исключительных си- туаций в процессе выступления.

Всем аннотациям советов передается строка с именем среза мно- жества точек сопряжения performance(), определяющая точки при- менения советов.

Обратите внимание, что кроме добавления аннотаций и пустого метода performance() реализация класса Audience осталась прежней. Это означает, что он все еще остается простым Java-объектом и может использоваться в этом его качестве. Он также может быть связан в конфигурации Spring, как показано ниже:

<bean  id="audience"

class="com.springinaction.springidol.Audience"   />

Поскольку класс Audience содержит собственные определения сре- за множества точек сопряжения и советов, больше нет необходимо- сти объявлять их в конфигурационном XML-файле. Последнее, что осталось сделать, – это применить Audience как аспект. Для этого необходимо объявить в контексте Spring компонент, реализующий автоматическое проксирование, который знает, как превратить ком- поненты, отмеченные аннотациями @AspectJ, в советы.

Для этой цели в состав Spring входит класс AnnotationAwareAspectJAu toProxyCreator, создающий объекты автоматического проксирования. Класс AnnotationAwareAspectJAutoProxyCreator можно зарегистрировать в контексте Spring с помощью элемента <bean>, но это потребует большого объема ввода с клавиатуры (уж поверьте… мне приходи- лось делать это несколько раз). Чтобы упростить эту задачу, фрейм- ворк Spring предоставляет собственный конфигурационный элемент в пространстве имен aop, гораздо более простой в запоминании, не- жели это длинное имя класса:

<aop:aspectj-autoproxy  />

Элемент <aop:aspectj-autoproxy/> создаст в контексте Spring ком- понент класса AnnotationAwareAspectJAutoProxyCreator и автоматически выполнит проксирование компонентов, имеющих методы, совпадаю- щие с объявлениями точек сопряжения в аннотациях @Pointcut, ко- торые присутствуют в компонентах, отмеченных аннотацией @Aspect.

Перед использованием элемента <aop:aspectj-autoproxy> нужно не забыть включить пространство имен aop в конфигурационном файле Spring:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

Вы должны понимать, что в качестве руководства к действию при создании аспектов элемент <aop:aspectj-autoproxy> использует толь- ко аннотации @AspectJ. В действительности эти аспекты все еще остаются аспектами Spring, а это означает, что, несмотря на исполь- зование аннотаций @AspectJ, советы могут применяться только к вызовам методов. Если необходимы дополнительные возможности AspectJ, следует использовать механизм AspectJ времени выполне- ния и не полагаться на возможность фреймворка Spring создавать аспекты на основе прокси-объектов.

Важно также отметить, что и элемент <aop:aspect>, и аннотации

@AspectJ обеспечивают эффективные способы превращения POJO в аспекты. Но элемент <aop:aspect> обладает одним важным пре- имуществом перед аннотациями @AspectJ – он не требует измене- ния исходного программного кода класса для преобразования его в аспект. Для применения аннотаций @AspectJ к классам и методам необходимо иметь исходные тексты, тогда как элемент <aop:aspect> может ссылаться на любой компонент.

Теперь посмотрим, как с помощью аннотаций @AspectJ создать совет, выполняемый и до, и после вызова целевого метода.

Источник:   Уоллс К., Spring в действии. – М.: ДМК Пресс, 2013. – 752 с.: ил.

По теме:

  • Комментарии