Spring. AOP в действии

max аватар
126
Находится в разделах:

Предположим, что вы хорошо проявили себя с предыдущим заданием. И теперь заказчики пришли к вам с новым заданием. В этом задании, менестрель  (поэт-музыкант из средневековья, сопровождавший рыцарей и воспевавших их действия) должен сопровождать каждого рыцаря, воспевая все его поступки и действия в песнях. Хм... менестрель, который поет о рыцаре? Ничего сложного. Создадим класс Minstrel:

Для поддержания стиля мышления dependency injection, мы изменяем класс KnightOfTheRoundTable для получения объекта Minstrel:

Все должно работать. Хотя стоп... есть небольшая проблемка. Каждый рыцарь должен остановиться и сказать менестрелю, чтобы тот пел песню перед тем, как рыцарь сможет продолжить свой квест. Затем, после квеста, рыцарь должен помнить о том, чтобы сказать менестрелю, чтобы тот продолжил петь. Сам факт того, что рыцарь должен помнить о том, чтобы остановиться и сказать менестрелю что делать, отвлекает рыцаря. 

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

Есть еще аспектный вариант. Следует "обернуть" менестреля в в аспект, который добавляет свой песнепишущий сервис к рыцарю. Затем сервис менестреля покрывает функционал рыцаря, при чем сам рыцарь даже не подозревает, что менестрель здесь.  

Создание аспекта

Существует несколько методов реализации аспектов в Spring. Для данного примера будем использовать новое пространство имен AOP, представленное в Spring 2.0.  Для того, чтобы начать, необходимо убедиться, что мы объявили пространство имен в контексте XML:

где ключевые строки: 

Используя объявленное пространство имен, мы готовы создавать аспект. Следующий кусок XML объявляет менестрель как бин в контексте спринга, а затем создает аспект, который обслуживает бин рыцаря.

Объявление бина менестреля

Создание аспекта менестреля

Создание набора точек входа для обертки embarkOnQuest():

Пение менестреля до:

Пение менестреля после:

В предыдущем листинге произошло очень многое, поэтому рассмотрим происходящее подробнее:

 

  • Первое - это объявление <bean>, создание бина менестреля в спринге. Это класс Minstrel. У него нет никаких зависимостей, поэтому нет необходимости внедрения его с чем-либо.
  • Следущий нюанс - элемент <aop:config>. Этот элемент показывает, что мы планируем сделать что-то с AOP. Большинство элементов конфигурации AOP должны быть помещены в <aop:config>.
  • Внутри <aop:config> мы имеем элемент <aop:aspect>. Этот элемент показывает, что мы объявляем аспект.  Функционал аспекта определен в бине, который ссылается атрибутом ref. В таком случае, бин minstrel, который является Minstrel, предоставляет функционал аспекта.
  • Аспект сделан из точек входа (это места, в которые будет применена функциональность аспектов) и advice (как применять функционал).  Элемент <aop:pointcut> определяет набор точек входа, которые затрагиваются выполнением метода embarkOnQuest().
  • Ну и наконец, рассмотрим AOP advice. Элемент <aop:before> объявляет, что метод singBefore() класса Minstrel должен быть вызван до pointcut., в то время как <aop:after> определяет, что метод singAfter() класса Minstrel должен быть вызван после pointcut. Набор точек входа в обоих случаях - ссылка на questPointcut, который представляет собой выполнение embarkOnQuest().
Вот и все! Мы только что обернули класс Minstrel  в Spring аспект. Не волнуйтесь о том, что не видите в этом смысла - вам достаточно будет увидеть несколько примеров, чтобы "очистить разум" и понять что к чему.
С рассмотренного примера следует взять два важных момента. 
  • Minstrel  - все еще POJO - нет ничего, что могло бы сказать, что Minstrel - аспект. Вместо этого, Minstrel был обернут в аспект декларативно, в контексте спринга.
  • Второй, и возможно, более важный, рыцарь больше не нуждается в том, чтобы напоминать менестрелю петь, когда нужно. Менестрель, как аспект, позаботится об этом автоматически. Рыцарь даже не знает, что менестрель существует. Следовательно, KnightOfTheRoundTable может быть откатан в более простую форму:
Использование AOP для записи всех действий рыцаря было забавной процедурой. Но Spring AOP может быть использован даже в более практичных примерах, чем сочинение бесполезных сонетов про рыцарей. 

 

 


Конец
Амос Бронсон Олкотт более, чем уверен в том, что мы добираемся до вершин чаще всего по обломкам наших заветных замыслов, обнаруживая, что успех нам принесли именно наши неудачи.

Перевод Spring in action.

А полная версия есть этого?

Отправить комментарий

CAPTCHA
Чтобы оставить комментарий, введите пожалуйста код, изображенный на картинке
Image CAPTCHA
Введите символы, изображенные на картинке