Pull to refresh

Аспектно ориентированное программирование в Android

Reading time 3 min
Views 12K
Услышав об аспектно ориентированном программировании я, как Android разработчик, сразу подумал, что на Android это вряд ли заработает, однако, решил попробовать. Я был очень удивлен, когда уже через 5 минут приложение, использующее AspectJ, успешно заработало на телефоне.

Не буду убеждать в необходимости использования аспектов в Android и приводить примеры «uses cases», просто приведу пример того, как добавить к своему приложению возможность использования аспектов. Что такое аспекты и для чего их использовать прекрасно описано, например, на wiki.

В качестве IDE для разработки я уже давно перешел на Android Studio, а следовательно использую gradle как систему сборки. Для нее и буду приводить пример конфигурирования.

Весь процесс подключения AspectJ состоит из следующих шагов:

  1. Подключаем плагин для сборки:
    В разделе buildscript скрипта сборки вашего проекта добавляем в dependencies строку:
    classpath 'com.uphyca.gradle:gradle-android-aspectj-plugin:0.9.+'

  2. В build.gradle модуля приложения добавляем:
    apply plugin: "android-aspectj"

  3. … а в зависимости модуля добавляем:
    dependencies {
        compile 'org.aspectj:aspectjrt:1.8.+'
    }
    

  4. Пишем сам аспект.
    Аспекты можно писать, используя специальный синтаксис, в файлах с расширением as, либо используя java + ряд анотаций. Поскольку Android Studio не включает AspectJ плагин, то я предпочел второй вариант (Для обладателей Ultimate версии IDEA доступны оба варианта):
    
    @Aspect
    public class MainActivityAspect {
        private static final String TAG = "helloaspectj";
    
        @Pointcut("execution(* ru.hoticecream.helloaspectj.ui.MainActivity.onCreate(..))")
        public void onCreateMethod(){}
    
        @Before("onCreateMethod()")
        public void doBeforeOnCreate(JoinPoint joinPoint) {
            Log.i(TAG, "AspectJ was here");
        }
    }
    

    Данный аспект встраивается до вызова метода MainActivity.onCreate, выводя соответствующее сообщение в лог.


Теперь, запустив приложение и открыв MainActivity, мы увидим в логе:
... I/helloaspectj﹕ AspectJ was here

Приведу еще пример использования аспекта.
Для этого в MainActivity добавим метод, устанавливающий определенному текстовому полю сообщение:

    private TextView mGreetingText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mGreetingText = (TextView) findViewById(R.id.greeting_message);
        setGreetingMessage("Hello Android");
    }

    private void setGreetingMessage(String message) {
        mGreetingText.setText(message);
    }

Как видите, поле принимает значение «Hello Android», запустив приложение можно в этом убедиться;)

Теперь добавим все в тот же класс аспекта следующие методы:

    @Pointcut("execution(* ru.hoticecream.helloaspectj.ui.MainActivity.setGreetingMessage(..))")
    public void setGreetingMessageMethod(){}

    @Around("setGreetingMessageMethod()")
    public void makeNasty(final ProceedingJoinPoint pjp)
            throws Throwable {
        Log.d(TAG, pjp.getSignature().toLongString());
        pjp.proceed(new Object[] { "Hello AspectJ" });
    }

В теперь этот аспект еще ищет метод setGreetingMessage и заменяет его вызов на содержимое метода makeNasty, используя для этого анотацию @Around

Запустив приложение, мы уже увидим «Hello AspectJ». При этом MainActivity.java мы не изменяли.

На этом все. Надеюсь статья была вам полезна.

Напоследок пару ссылок:
Tags:
Hubs:
+13
Comments 9
Comments Comments 9

Articles