Аспектно-орієнтоване програмування. Основи

Продовжимо тему, розпочату в минулій слюсарно-програмістській статті про AspectJ і open source розширення для цієї бібліотеки aspectj-scripting. У цій замітці розглянемо які завдання вирішує аспектно-орієнтоване програмування (AOP) на прикладі та синтаксисі найвідомішої бібліотеки серед адептів цієї методології. AspectJ - дитя Xerox PARC, тепер повнолітнє і живе в Eclipse Foundation.


(фото зі статті на lurkmore про євроремонт)

Ймовірно, стаття не буде цікава тим хто часто використовує у своїй роботі AOP і розуміє що це таке. У коментарях вітаються як конструктивні зауваження так і веселий холівар!

Disclaimer: Я не теоретик, тому розказане в статті суб'єктивно, пропущено через призму досвіду.

Навіщо всі ці складнощі, інший підхід до проектування систем, коли є об'єктно-орієнтоване програмування? Новий синтаксис, якісь аспекти, зрізи (pointcut) - адже все в результаті перетворюється на ті ж інструкції виконувані jvm.

Питання у зручності розробки, легкості модифікації, тестування та вартості підтримки системи. Аспекти - це доповнення до ОВП програмам, інша парадигма при розробці і проектуванні програм, що не суперечить використанню об'єктної моделі в додатку. Аналогія, яка відразу приходить на думку - аналіз звукових даних. У часовій області з вихідним сигналом складно виконати обробку та аналіз. Але при переведенні в частотне уявлення легко відфільтрувати шуми певної частоти, виділити ноти в мелодії, посилити звук голосу і т. п. Так само і аспекти дозволяють легко працювати з багатьма завданнями в іншому уявленні програми і виділити наскрізну функціональність у вигляді аспекту. При вмілому застосуванні AOP допомагає «розплутати» «заплутаний» код програми.

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

Почнемо з поняття що таке advice в AspectJ - це те як буде застосовуватися аспект в зрізі коду (pointcut): перед зрізом (BEFORE), після (AFTER), після успішного повернення (AFTER RETURNING), у разі помилки в точці зрізу (AFTER THROWING), або повний контроль над ситуацією (AROUND) де самостійно треба викликати вихідний код в зрізі, передавати параметри і обробки точки виконання.

Pointcut або зріз - це опис того, де ми будемо впроваджувати у вихідну програму аспект. Синтаксис досить багатий і дозволяє описати складні правила, що визначають точки зрізу. Наприклад, конструювання об'єкта, блоки статичної ініціалізації, виклик конструктора, доступ до полів об'єкта на читання/запис, конструювання об'єкта, блок 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, а агент у центральному репозитарії. У попередній публікації використовував цю бібліотеку для модифікації поведінки maven plugin Про інші приклади використання аспектно-орієнтованого програмування в практиці, розповім в наступних статтях.

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

COM_SPPAGEBUILDER_NO_ITEMS_FOUND