Android 基于AOP监控之——AspectJ使用指南

原创 2016年05月27日 22:01:34

如何使用

在Eclipse中已经有AJDT插件集成了AspectJ编译器的使用和关键字的声明。但是在Android Studio中没有这样的官方插件。因此,这里讲一下如何在Android Studio中使用AspectJ。详细了解AspectJ的使用请看Android基于AOP的非侵入式监控

AspectJ的使用核心就是它的编译器,它就做了一件事,将AspectJ的代码在编译期插入目标程序当中,运行时跟在其它地方没什么两样,因此要使用它最关键的就是使用它的编译器去编译代码ajc。ajc会构建目标程序与AspectJ代码的联系,在编译期将AspectJ代码插入被切出的PointCut中,已达到AOP的目的。
因此,无论在什么IDE上(如果使用命令行就可以直接使用ajc编译了),问题就是让IDE使用ajc作为编译器编译代码。

使用方法

1、插件:网上有人在github上提供了集成的插件gradle-android-aspectj-plugin,一开始我也是用的这个,但是在项目当中,无法兼容databinding,这个问题现在作者依然没有解决。

2、Gradle配置:国外还有一个大牛在build文件中添加了一些脚本,也能够在AS中使用,但是脚本定义的任务有点麻烦(Gradle基础不好的看不懂,我就是)。不过正是这位大牛解决了我项目上遇到的问题。文章地址:Aspect Oriented Programming in Android

下面就介绍一下第二种方法的具体的使用步骤。

Step

1、创建AS原工程

这里写图片描述

2、创建module(Android Library),然后添加AspectJ依赖,必须添加至module中,添加至APP工程中ajc编译器是不会重构目标代码的。

compile 'org.aspectj:aspectjrt:1.8.9'

3、编写build脚本,添加任务,使得IDE使用ajc作为编译器编译代码。

这里,主工程和Module都需要对构建脚本添加一些任务,目的就是为了建立两者的通信,使得IDE使用ajc编译代码。
build.gradle(app):

import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.aspectj:aspectjtools:1.8.9'
    }
}

apply plugin: 'com.android.application'

repositories {
    mavenCentral()
}

dependencies {
    compile project(':aspectjlibrary')
}

android {
    compileSdkVersion 21
    buildToolsVersion '22.0.1'

    buildTypes {
        debug {
            minifyEnabled false  // should disable proguard in debug builds
        }
    }
    defaultConfig {
        applicationId "com.example.lingyimly.try2"
        minSdkVersion 15
        targetSdkVersion 21

    }

    lintOptions {
        abortOnError true
    }

}

final def log = project.logger
final def variants = project.android.applicationVariants

variants.all { variant ->
    if (!variant.buildType.isDebuggable()) {
        log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")
        return;
    }

    JavaCompile javaCompile = variant.javaCompile
    javaCompile.doLast {
        String[] args = ["-showWeaveInfo",
                         "-1.5",
                         "-inpath", javaCompile.destinationDir.toString(),
                         "-aspectpath", javaCompile.classpath.asPath,
                         "-d", javaCompile.destinationDir.toString(),
                         "-classpath", javaCompile.classpath.asPath,
                         "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]
        log.debug "ajc args: " + Arrays.toString(args)

        MessageHandler handler = new MessageHandler(true);
        new Main().run(args, handler);
        for (IMessage message : handler.getMessages(null, true)) {
            switch (message.getKind()) {
                case IMessage.ABORT:
                case IMessage.ERROR:
                case IMessage.FAIL:
                    log.error message.message, message.thrown
                    break;
                case IMessage.WARNING:
                    log.warn message.message, message.thrown
                    break;
                case IMessage.INFO:
                    log.info message.message, message.thrown
                    break;
                case IMessage.DEBUG:
                    log.debug message.message, message.thrown
                    break;
            }
        }
    }
}


build.gradle(module):

import com.android.build.gradle.LibraryPlugin
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main

apply plugin: 'com.android.library'
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.0'
        classpath 'org.aspectj:aspectjtools:1.8.9'
        classpath 'org.aspectj:aspectjweaver:1.8.9'
    }
}


repositories {
    mavenCentral()
}
dependencies {
    compile 'org.aspectj:aspectjrt:1.8.9'
    compile 'com.android.support:appcompat-v7:22.2.1'
}
android {
    compileSdkVersion 22
    buildToolsVersion '23.0.1'

    lintOptions {
        abortOnError false
    }

}

android.libraryVariants.all { variant ->
    LibraryPlugin plugin = project.plugins.getPlugin(LibraryPlugin)
    JavaCompile javaCompile = variant.javaCompile
    javaCompile.doLast {
        String[] args = ["-showWeaveInfo",
                         "-1.5",
                         "-inpath", javaCompile.destinationDir.toString(),
                         "-aspectpath", javaCompile.classpath.asPath,
                         "-d", javaCompile.destinationDir.toString(),
                         "-classpath", javaCompile.classpath.asPath,
                         "-bootclasspath", plugin.project.android.bootClasspath.join(
                File.pathSeparator)]

        MessageHandler handler = new MessageHandler(true);
        new Main().run(args, handler)

        def log = project.logger
        for (IMessage message : handler.getMessages(null, true)) {
            switch (message.getKind()) {
                case IMessage.ABORT:
                case IMessage.ERROR:
                case IMessage.FAIL:
                    log.error message.message, message.thrown
                    break;
                case IMessage.WARNING:
                case IMessage.INFO:
                    log.info message.message, message.thrown
                    break;
                case IMessage.DEBUG:
                    log.debug message.message, message.thrown
                    break;
            }
        }
    }
}

4、编写AspectJ切面程序代码

package com.example.lingyimly.aspectj;

import android.util.Log;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

/**
 * Created by lingyi.mly on 2016/5/27.
 */
@Aspect
public class TraceAspect {
    private String TAG = "TAG ";
    private static final String POINT_METHOD = "execution(* com.example.lingyimly.try3.MainActivity.*(..))";
    private static final String POINT_CALLMETHOD = "call(* com.example.lingyimly.try3.MainActivity.*(..))";
    @Pointcut(POINT_METHOD)
    public void methodAnnotated(){}
    @Pointcut(POINT_CALLMETHOD)
    public void methodCallAnnotated(){}
    @Around("methodAnnotated()")
    public Object aronudWeaverPoint(ProceedingJoinPoint joinPoint) throws Throwable {
        joinPoint.proceed();
        String result = "----------------------------->aroundWeaverPoint";
        Log.e(TAG,"----------------------------->aroundWeaverPoint");
        return  result;//替换原方法的返回值
    }
    @Before("methodCallAnnotated()")
    public void beforecall(JoinPoint joinPoint){
        Log.e(TAG,"beforecall");
    }
}

5 运行结果

05-27 21:01:30.618 25192-25192/? E/TAG: beforecall
05-27 21:01:30.678 25192-25192/? E/TAG: beforecall
05-27 21:01:30.678 25192-25192/? E/TAG: ----------------------------->aroundWeaverPoint
05-27 21:01:30.678 25192-25192/? E/TAG: MainActivity  ----------------------------->aroundWeaverPoint
05-27 21:01:30.678 25192-25192/? E/TAG: ----------------------------->aroundWeaverPoint
05-27 21:39:20.108 27390-27390/? E/TAG: MainActivity  From MainActivity

DEMO地址

AndroidAOP

版权声明:本文为博主原创文章,转载请说明出处。

深入理解Android之AOP

深入理解Android之AOP格式更加精美的PDF版请到:http://vdisk.weibo.com/s/z68f8l0xTgCLK 下载一、闲谈AOP大家都知道OOP,即ObjectOriente...
  • Innost
  • Innost
  • 2015年10月24日 19:48
  • 47657

使用AspectJ在Android中实现Aop

开题上一篇文章Android Aop预研中介绍了Aop的各种实现方式,并且在最后提到,选择AspectJ作为合适的开发方式。这篇文章通过我自己编写的一个例子,来说明AspectJ的使用。首先要声明,使...
  • kangaroo835127729
  • kangaroo835127729
  • 2016年07月24日 16:36
  • 10148

Android 开发中使用 AOP

大家对AOP应该都不陌生, 就算没有用过也肯定听说过. 用过或了解过Java AOP的同学应该都知道AspectJ的大名. 因为AspectJ与java程序完全兼容,几乎是无缝关联, 所以只需要做一些...
  • l2show
  • l2show
  • 2017年03月19日 14:19
  • 1665

Android进阶系列之AOP面向切面编程

Android的博大精深,不是一言两语能够说明道清的,它的魅力只有亲身去接触才能体会。就像美女一样 我先在这里申明一下,我这篇AOP只是学习笔记,适合入门级选手,如果阁下是大神想要参考AOP,那么...
  • sw5131899
  • sw5131899
  • 2016年12月26日 17:30
  • 4482

Android AOP实现原理全解析

深入理解Android之AOP
  • sinat_22657459
  • sinat_22657459
  • 2016年12月25日 15:15
  • 534

Android中的AOP

各位同学,目前已经转入至简书,欢迎来搞事情简书地址: http://www.jianshu.com/users/99f514ea81b3/timeline说一件开心的事情,我的这篇文章将被刊登在 鸿洋...
  • sinat_15877283
  • sinat_15877283
  • 2017年03月10日 11:35
  • 396

Android中的AOP编程之AspectJ实战实现数据埋点

文章背景 最近在给某某银行做项目的时,涉及到了数据埋点,性能监控等问题,那我们起先想到的有两种方案,方案之一就是借助第三方,比如友盟、Bugly等,由于项目是部署在银行的网络框架之内的,所以该方案不可...
  • XiNanHeiShao
  • XiNanHeiShao
  • 2017年07月01日 22:55
  • 2479

Android Aop预研

预研目的公司要求,希望我整理一下项目中的log日志,由于当前项目已经很庞大,包含多个自主开发的library,并且由多个开发人员共同完成。不同的同事,打log的方式都不一样,没有同一个的格式,因此我探...
  • kangaroo835127729
  • kangaroo835127729
  • 2016年07月24日 15:26
  • 3513

Android AOP 总结

AndroidAOP 总结 一、AOP 1.1 什么是AOP AOP,AspectOriented Programming 面向切面编程 OOP,Object-orientedprogramming面...
  • chenzhiqin20
  • chenzhiqin20
  • 2017年03月16日 21:24
  • 614

AOP在Android中的应用

官网地址:http://fernandocejas.com/2014/08/03/aspect-oriented-programming-in-android/ OOP (面向对象编程)针对业务...
  • huohacker
  • huohacker
  • 2017年02月23日 14:45
  • 324
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android 基于AOP监控之——AspectJ使用指南
举报原因:
原因补充:

(最多只允许输入30个字)