Аспектно-ориентированное программирование Copyright © Мигинский Д.С., 2008-2009 Предпосылки для появления АОП Чрезмерное усложнение дизайна для реализации принципа модульности или его нарушение при реализации ряда требований Например: •журналирование событий (для.

Download Report

Transcript Аспектно-ориентированное программирование Copyright © Мигинский Д.С., 2008-2009 Предпосылки для появления АОП Чрезмерное усложнение дизайна для реализации принципа модульности или его нарушение при реализации ряда требований Например: •журналирование событий (для.

Аспектно-ориентированное
программирование
Copyright © Мигинский Д.С., 2008-2009
Предпосылки для появления
АОП
Чрезмерное усложнение дизайна для реализации
принципа модульности или его нарушение при
реализации ряда требований
Например:
•журналирование событий (для отладки и т.д.)
•персистентность
•транзакционность
•информационная безопасность
•обработка ошибок
Cross-cutting concern


Сквозная функциональность –
функциональность, затрагивающая
существенную часть модулей системы
Сквозная функциональность не
может быть выделена в отдельный
модуль без существенного
усложнения дизайна
Недостатки ООП/ООД




Существенное влияние ограничений и условностей языков
программирования (в первую очередь C++ и Java)
Ориентированность ООД на простейшую реализацию
объектной модели
Невозможность во многих случаях соблюдения собственных
принципов
Как следствие – необходимость использования большого
количества точечных решений, как например GOF-patterns
Распространенные техники


Шаблоны проектирования
Метаописания (напр. Hibernate, Eclipse RCP,
WSDL)

Аннотации (Java, C#)

Интроспекция
Задача: наблюдение за
изменением данных
Editor
<<read>>
Drawer1
<<modify>>
<<notify>>
Проблема:
•циклическая зависимость
Document
<<notify>>
Drawer2
<<read>>
Постановка
При внешних изменениях
документа должна обновляться его
визуализация
Решение 1: Observer
Проблемы:
•усложнение дизайна
•документ получает несвойственную
для него функциональность
(нарушение One-Responsibility Rule)
Язык AspectJ
Проект AspectJ
http://www.eclipse.org/aspectj/
Руководство по языку
http://www.eclipse.org/aspectj/doc/released/progguide/index.html
AspectJ Development Tools for Eclipse
http://www.eclipse.org/ajdt/
Основные понятия AOP
(AspectJ)

Join point (точка выполнения) – определенная
идентифицируемая точка выполнения программы

Pointcut (срез) – набор (класс) точек выполнения программы

Advice – изменение функциональности, применяемое к точке
выполнения

Introduction – дополнительное внешнее свойство уже
существующего класса

Aspect (аспект) – организационная сущность для всего
вышеперечисленного
Другие встречающиеся
термины




Wrapping
Weaving
Intercepting
…
Задача: «внешний»
рефакторинг кода
Проблемы:
•нарушение инкапсуляции
в Rectangle
•неконтролируемые изменения
Rectangle
•отсутствие контроля ошибок
Предположения:
•Rectangle инстанциируется только в
RectangleFactory
•Client не должен модифицировать
Rectangle
•Размеры прямоугольника
неотрицательны
АОП-решение
public aspect RectangleConstraints {
pointcut rcSetter (double newval) :
set (double Rectangle.*) && args (newval);
void around (double newval) : rcSetter (newval){
if (newval >= 0) proceed (newval);
else proceed (0);
}
pointcut wrongInstance () :
call (Rectangle.new(..)) && !within (RectangleFactory);
declare warning: wrongInstance ():
"Incorrect instantiation context for Rectangle";
declare warning: set (double Rectangle.*) && !within
(RectangleFactory):
"Incorrect modification context for Rectangle";
}
set/get pointcuts
//перехват присваивания любому полю типа int любого класса
//не рекомендуется к использованию
pointcut setAnyInt1 (): set (int *);
//перехват присваивания любому полю типа int в классе Class1
//с возможностью использования аргумента
pointcut setAnyInt2 (int val):
set (int Class1.*) && args (val);
//--//-- для любого класса, имя которого начинается с Class и
//имя аргумента начинается с f
pointcut setAnyInt3 (int val):
set (int Class*.f*) && args (val);
//перехват использования поля в правой части
pointcut getAnyInt1 (int val):
get (int Class*.f*) && args (val);
call/execute pointcuts
//перехват вызова метода любого класса, начинающегося с set,
//с произвольным списком аргументов и возвращаемым значением
//не рекомендуется к использованию
pointcut setterAny (): call (* *.set* (..));
//перехват вызова метода любого класса, начинающегося с set,
//с произвольным возвращаемым значением и аргументом типа int
//не рекомендуется к использованию
pointcut setterAnyInt (int val):
call (* *.set* (int)) && args (val);
//перехват вызова set* вне контекста класса ValueManager
pointcut setAnyInt2 (int val):
call (* *.set* (int)) && args (val) &&
!within (ValueManager);
Context pointcuts





within (Type) – внутри определенного
класса
whithincode (Method) – внутри
определенного метода
this (Type || id) – вызывающий объект
заданного типа
target (Type || id) – объект вызываемого
метода заданного типа
args (Type[] || id[]) – аргументы
определенного типа
Разновидности pointcut






вызов метода
доступ к атрибуту (get/set)
генерация/перехват исключения
инициализация класса/объекта
контекст (в определенном классе или
методе)
…
Разновидности advice



before – до
after – после (выполнения тела
метода, возврата значения,
генерации исключения)
around - вместо
Тело advice
advice по сути является неявно вызываемым методом,
тело advice аналогично телу любого метода + ряд
дополнительных возможностей:
•thisJoinPoint – объект, описывающий контекст
вызова (join point)
•proceed (<args>) – вызов исходной join point
(применительно к around)
inter-type declarations
//определение ошибок и предупреждений впемени компиляции
declare warning: <pointcut>: “Message”
declare error: <pointcut>: “Message”
//определение суперкалссов/интерфейсов
declare parents: Document implements Serializable
declare parents: Document extends DataqObject
//определение/реализация методов
public boolean Document.isEmpty () {…}
//определение атрибутов
private String Document.name = “Empty”
Технические возможности
AspectJ




точечная модификация императивной
части кода
модификация определений классов:
определение новых методов,
атрибутов, суперклассов и
интерфейсов
контекстный полиморфизм
управление компиляцией
Задача: разграничение
доступа
Решение 1
Недостаток: необходимо модифицировать код
Service
Решение 2
Недостаток: авторизуются только запросы клиента,
но не внутренние сообщения Service
Решение 3 (АОП)
«Принципы»
неиспользования АОП



АОП – это НЕ средство взлома чужого кода
АОП – это НЕ способ создания
неуправляемого кода (см. также
«самомодифицирующийся код», «блюдо
спагетти»)
АОП – это НЕ то средство, которое
необходимо применять всегда и везде
Генерализация аспектов:
пример использования
Применение генерализации
аспектов: способ 1


Базовый (абстрактный) аспект
определяет набор pointcuts, как точек
расширения системы
Аспект-наследник определяет
поведение в терминах advices
Применение генерализации
аспектов: способ 2


Базовый (абстрактный) аспект
определяет набор абстрактных
pointcuts, а также некоторую
функциональность в терминах advices
Аспект-наследник связывает
функциональность с кодом путем
определения pointcuts
Observer: реализация в
AspectJ



Запустите Eclipse
Создайте новый проект
File->New->Project->AspectJ->
AspectJ Examples->Observer Example
Разберите код и объясните его
Задача
Реализуйте по аналогии с примером Observer
универсальный абстрактный аспект, который
обеспечивал бы функциональность undo/redo. Привязка
к конкретным классам должна осуществляться за счет
аспектов-наследников.
Продемонстрируйте работу аспекта на примере
собственной реализации класса, представляющего
двумерную точку (либо любого другого класса данных).
Класс должен реализовать только функции бизнеслогики (аксессоры к атрибутам).