- PVSM.RU - https://www.pvsm.ru -

Аспектно-ориентированное программирование. Основы

Продолжим тему, начатую в прошлой слесарно-программистской статье [1] про AspectJ и open source расширение для этой библиотеки aspectj-scripting [2]. В этой заметке рассмотрим какие задачи решает аспектно-ориентированное программирование (AOP) на примере и синтаксисе самой известной библиотеки среди адептов этой методологии. AspectJ — дитя Xerox PARC, теперь совершеннолетнее и живущее в Eclipse Foundation.

Аспектно-ориентированное программирование. Основы - 1
(фото из статьи на lurkmore про евроремонт)

Вероятно, статья не будет интересна тем кто часто использует в своей работе AOP и понимает что это такое. В комментариях приветствуются как конструктивные замечания так и веселый холивар!

Disclaimer: Я не теоретик, поэтому рассказанное в статье субъективно, пропущено через призму опыта.

Зачем все эти сложности, другой подход к проектированию систем, когда есть объектно-ориентированное программирование? Новый синтаксис, какие-то аспекты, срезы(pointcut) — ведь все в итоге превращается в те же инструкции выполняемые jvm.

Вопрос в удобстве разработки, легкости модификации, тестирования и стоимости поддержки системы. Аспекты — это дополнение к ООП программам, другая парадигма при разработке и проектировании программ, не противоречащая использованию объектной модели в приложении. Аналогия, которая сразу приходит на ум — анализ звуковых данных. В временной области с исходным сигналом сложно выполнить обработку и анализ. Но при переводе в частотное представление легко отфильтровать шумы определенной частоты, выделить ноты в мелодии, усилить звук голоса и т.п. Так же и аспекты позволяют легко работать со многими задачами в другом представлении программы и выделить сквозную функциональность в виде аспекта. При умелом применении AOP помогает «распутать» «запутанный» код программы.

Возникает возможность убрать инструкции ведения журнала операций(логгинга) и обработки системных ошибок из бизнес-логики приложения, уменьшить количество бойлерплейт кода, проверять права доступа пользователя при обращении к определенным методам или полям класса, декларативно управлять транзакциями базы данных, выполнять свое инструментирующее профилирование интересующего вас участка кода, в котором учитывается не только факт вызова и время выполнения операции но и некоторый контекст, кеширование «тяжелых» операций бизнес логики если у них нет побочного эффекта, поиск мест программы в которых конструирование объектов определенного типа. Этим не ограничивается список того, для чего может быть удобно AOP. Например, в проекте на работе, я применяю аспекты для тестирования распределенного приложения, сбора метрик в нем, имитации ошибок базы данных и таймаутов внутри jdbc драйвера oracle и сетевых взаимодействий.

Начнем с понятия что такое advice в AspectJ [3] — это то как будет применяться аспект в срезе кода(pointcut): перед срезом (BEFORE), после (AFTER), после успешного возврата (AFTER RETURNING), в случае ошибки в точке среза (AFTER THROWING), или полный контроль над ситуацией (AROUND) где самостоятельно надо вызывать исходный код в срезе, передавать параметры и обрабатывать ошибки выполнения в точке среза.

Pointcut или срез — это описание того, где мы будем внедрять в исходную программу аспект. Синтаксис достаточно богатый [4] и позволяет описать сложные правила, определяющие точки среза. Например, конструирование объекта, блоки статической инициализации, вызов конструктора, доступ к полям объекта на чтение/запись, конструирование объекта, блок catch, методы с какой-либо аннотацией, вызов метода с параметрами определенного типа, имя метода по маске и т.п. + логические операции в синтаксисе pointcut. Конечно, волшебства в программировании нет, что добавляет ограничения на то что инлайнится в байт коде и не доступно в pointcut. Так же не все мыслимые точки среза можно указать декларативно, что иногда требует анализа контекста вызова в коде реализации аспекта.

Параметр точки соединения (join point) в аспекте позволяет получить значения аргументов, узнать место где фактически произошел вызов аспекта в срезе, получить this объекта и т.п. В случае с AROUND advice тут же можно выполнить фактический вызов, изменить его параметры и получить возращаемое значение или обработать ошибку.

Все то, что на первый взгляд кажется магией, в AspectJ либо реализуется плагином во время сборки проекта (weaving to bytecode), либо java агентом с помощью модификации байт кода программы во время загрузки классов(load-time weaving). AspectJ — зрелый AOP фреймворк с огромным комьюнити, множеством публикаций про него, хорошей документацией, достаточно стабильный, интегрированный в разнообразные системы сборки, интеграция в Spring, с хорошей поддержкой в IDE.

В aspectj-scripting (расширении AspectJ java агента) есть возможность для аспектов во время выполнения загружать классы из maven репозитария, считывать конфигурацию агента не только из файла и classpath, но и с http сервера. Это может сильно помочь в тестировании, профилировании и модификации распределенного java приложения. Код доступен на github [2], а агент в центральном репозитарии [5]. В прошлой публикации использовал эту библиотеку для модификации поведения [1] maven plugin Про другие примеры использования аспектно-ориентированного программирования в практике, расскажу в следующих статьях.

Как вишенка на торте украшает его и делает более вкусным, так же и аспектно-ориентированное программирование в объектно-ориентированной программе упрощает разработку, модификацию и тестирование. Важно не увлекаться применением AOP в проекте — чтобы не получилась кастрюля вишни с ложкой крема сверху!

Аспектно-ориентированное программирование. Основы - 2

Автор: igor_suhorukov

Источник [6]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/java/87859

Ссылки в тексте:

[1] в прошлой слесарно-программистской статье: http://habrahabr.ru/post/254571

[2] aspectj-scripting: https://github.com/igor-suhorukov/aspectj-scripting

[3] AspectJ: https://eclipse.org/aspectj

[4] достаточно богатый: https://eclipse.org/aspectj/doc/next/progguide/semantics-pointcuts.html

[5] в центральном репозитарии: http://repo1.maven.org/maven2/com/github/igor-suhorukov/aspectj-scripting/1.0/aspectj-scripting-1.0-agent.jar

[6] Источник: http://habrahabr.ru/post/254791/