Аспектно-ориентированная парадигма программирования хорошо зарекомендовала себя при использовании в разработке высоконагруженных систем. Она позволяет создавать общую логику для разных классов, не связанных наследованием или агрегацией. Однако для платформы Android не существует реализации аспектного компилятора. Фреймворк ProxPects предназначен для создания аспектов и генерации прокси-объектов [1], при вызове методов которых будут применяться advice’ы аспектов.
Ключевые слова:Android, Java, аспектно-ориентированное программирование, фреймворк
Существующие парадигмы программирования предоставляют определённые способы для разделения и выделения функциональности: функции, модули, классы, но некоторую функциональность с помощью предложенных методов невозможно выделить в отдельные сущности. Такую функциональность называют сквозной, так как она распределена по различным модулям программы.
Логирование, обработка исключений, управление транзакциями, кеширование [2] и ограничение времени выполнения — примеры сквозной функциональности. Другие примеры: трассировка; аутентификация и проверка прав доступа; контрактное программирование. Для программы, написанной в парадигме ООП, любая функциональность, по которой не была проведена декомпозиция, является сквозной.
Цель работы.
Целью работы является разработка фреймворка под ОС Android для реализации возможности использования АОП при разработке приложений для этой ОС.
Описание фреймворка.
Принцип работы фреймворка:
− Для реализации сквозной логики необходимо иметь возможность перехватывать вызовы методов объектов. Для этого можно воспользоваться механизмом проксирования — создаётся InvocationHandler, управляющий процессом выполнения метода и имеющий доступ к оригинальному объекту.
− Вызов метода делится на три части: before, around и after. Каждый аспект также реализует три эти метода и может вернуть результат или создать исключение раньше, чем управление получит оригинальный объект.
Перед тем, как аспекты можно будет использовать, необходимо провести проксирование. Для этого надо зарегистрировать аспект в фреймворке и передать в фабричный метод оригинальный объект и его интерфейс. В языке Java, использующемся для разработки приложений в ОС Android создание интерфейса является необходимостью для создания прокси-объектов. Это ограничение можно обойти, используя CGLIB, однако это увеличит нагрузку на процессор и увеличит время создания прокси.
Фреймворк обходит все методы интерфейса и обрабатывает их аннотации. Если аннотация помечена аннотацией @Aspect, то для этого метода будет создан обработчик вызова со списком аспектов, которым необходимо передать управление в случае вызова. При этом учитывается порядок аннотаций, а также наследование:
− Первым управление получает аспект, объявленный раньше, т. е. ближе к телу метода.
− Если один и тот же аспект применяется к родительскому классу и к классу наследнику, будут использованы параметры класса наследника.
− В случае если метод класса реализующего интерфейс переопределяет аспект, то будут использованы его параметры.
Интерфейс InvocationHandler позволяет создавать checked исключения при обработке вызовов методов, однако в разработанном фреймворке аспектам прямо запрещается создание checked исключений, чтобы избежать ситуаций, когда в try-catch блок оборачивается метод в сигнатуре которого нет checked исключения. Таким образом все исключения, которые могут создавать аспекты, являются runtime исключениями и могут быть обработаны только в try-catch блоках для runtime исключений или в UncaughtExceptionHandler.
Рис. 1. Основные классы фреймворка
Реализованные аспекты.
Для тестирования возможностей фреймворка были реализованы следующие аспекты: Cacheable и Timeout.
Cacheable-аспект позволяет кэшировать результаты вызова метода. Ключом в кэше является список аргументов. Параметром аннотации является ttl — время хранения кэшированного значения (по умолчанию -1, бесконечное хранение).
Timeout-аспект позволяет ограничивать время выполнения метода, таким образом методы, которые могут выполнятся длительное/неограниченное время, гарантированно не превысят заданный разработчиком промежуток времени. Параметрами аннотации являются timeout (по умолчанию 1 секунда) — максимальное возможное время выполнение метода и maxParallel — количество возможных параллельных вызовов метода (по умолчанию 1).
Рис. 2. Пример использования аспекта Cacheable в JUnit-тесте
Результаты.
В результате разработки был создан фреймворк «ProxPects». Данный фреймворк позволяет использовать аспектно-ориентированную парадигму при разработке приложений для AndroidOS. Исходные коды фреймворка опубликованы в открытом репозитории GitHub. Фреймворк также можно подключить, используя Maven/Gradle через сервис jitpack.
Варианты развития фреймворка.
Прототип фреймворка «ProxPects» может быть доработан следующими улучшениями:
− Создание плагина для AOT компиляции, чтобы ускорить создание прокси-объектов и избежать runtime сканирования классов.
− Использование CGLIB для создания прокси-объектов без необходимости создания java-интерфейса класса.
Литература:
- Java class Proxy // Docs Oracle. URL: https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html (дата обращения: 27.11.2016).
- Transactions, Caching and AOP: understanding proxy usage in Spring // Spring. URL: https://spring.io/blog/2012/05/23/transactions-caching-and-aop-understanding-proxy-usage-in-spring (дата обращения: 27.11.2016).