Android AOP(二):AspectJ在Android中实现Aop

AspectJ

AspectJ实际上是对AOP编程思想的一个实践,当然,除了AspectJ以外,还有很多其它的AOP实现,例如ASMDex,但目前最好、最方便的,依然是AspectJ。

AOP的用处非常广,从Spring到Android,各个地方都有使用,特别是在后端,Spring中已经使用的非常方便了,而且功能非常强大,但是在Android中,AspectJ的实现是略阉割的版本,并不是所有功能都支持,但对于一般的客户端开发来说,已经完全足够用了。

在Android上集成AspectJ实际上是比较复杂的,不是一句话就能compile,但是,鄙司已经给大家把这个问题解决了,大家现在直接使用这个SDK就可以很方便的在Android Studio中使用AspectJ了。Github地址如下:

https://github.com/HujiangTechnology/gradle_plugin_android_aspectjx

另外一个比较成功的使用AOP的库是Jake大神的Hugo:

https://github.com/JakeWharton/hugo

AOP 能做什么?

持久化
性能监控
数据校验
缓存

1.引入 AspectJ

app/build.grade加入以下配置项,app和library配置相同:

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

apply plugin: 'com.android.library'

android {
    compileSdkVersion 26



    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }



}

repositories {
    jcenter()
    mavenCentral()
}

buildscript {
    repositories {
        jcenter()
        mavenCentral()
    }
    dependencies {
        classpath 'org.aspectj:aspectjtools:1.8.9'
        // 如果是android library 要加上
        classpath 'org.aspectj:aspectjweaver:1.8.9'
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'org.aspectj:aspectjrt:1.8.9'
//    compile 'com.android.support:appcompat-v7:27.1.1'
}

android.libraryVariants.all { variant ->
    JavaCompile javaCompile = variant.javaCompile
    javaCompile.doLast {
        String[] args = ["-showWeaveInfo",
                         "-1.8",
                         "-inpath", javaCompile.destinationDir.toString(),
                         "-aspectpath", javaCompile.classpath.asPath,
                         "-d", javaCompile.destinationDir.toString(),
                         "-classpath", javaCompile.classpath.asPath,
                         "-bootclasspath", 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
            }
        }
    }
}

2.AspectJ 语法

JPoint:代码可注入的点,比如一个方法的调用处或者方法内部、“读、写”变量等。
Pointcut:用来描述 JPoint 注入点的一段表达式,比如:调用 Animal 类 fly 方法的地方,call(* Animal.fly(..))。
Advice:常见的有 Before、After、Around 等,表示代码执行前、执行后、替换目标代码,也就是在 Pointcut 何处注入代码。
Aspect:Pointcut 和 Advice 合在一起称作 Aspect。

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

3.使用

统计一下某个方法的运行时间

public class StopWatch {
    private long startTime;
    private long endTime;
    private long elapsedTime;

    public StopWatch() {
        //empty
    }

    private void reset() {
        startTime = 0;
        endTime = 0;
        elapsedTime = 0;
    }

    public void start() {
        reset();
        startTime = System.nanoTime();
    }

    public void stop() {
        if (startTime != 0) {
            endTime = System.nanoTime();
            elapsedTime = endTime - startTime;
        } else {
            reset();
        }
    }

    public long getTotalTimeMillis() {
        return (elapsedTime != 0) ? TimeUnit.NANOSECONDS.toMillis(endTime - startTime) : 0;
    }

}
public class DebugLog {
    private DebugLog() {}

    /**
     * Send a debug log message
     *
     * @param tag Source of a log message.
     * @param message The message you would like logged.
     */
    public static void log(String tag, String message) {
//        Log.i(tag, message);
        System.out.print(message);
    }
}
@Retention(RetentionPolicy.CLASS)
@Target({ ElementType.CONSTRUCTOR, ElementType.METHOD })
public @interface DebugTrace {}
@Aspect
public class TraceAspect {

    private static final String POINTCUT_METHOD =
            "execution(@com.example.libraryaspectj.DebugTrace * *(..))";

    private static final String POINTCUT_CONSTRUCTOR =
            "execution(@com.example.libraryaspectj.DebugTrace *.new(..))";

    @Pointcut(POINTCUT_METHOD)
    public void methodAnnotatedWithDebugTrace() {}

    @Pointcut(POINTCUT_CONSTRUCTOR)
    public void constructorAnnotatedDebugTrace() {}

    @Around("methodAnnotatedWithDebugTrace() || constructorAnnotatedDebugTrace()")
    public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        String className = methodSignature.getDeclaringType().getSimpleName();
        String methodName = methodSignature.getName();

        final StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        Object result = joinPoint.proceed();
        stopWatch.stop();

        DebugLog.log(className, buildLogMessage(methodName, stopWatch.getTotalTimeMillis()));
        Log.i("*** yang",buildLogMessage(methodName, stopWatch.getTotalTimeMillis()));
        return result;
    }

    /**
     * Create a log message.
     *
     * @param methodName A string with the method name.
     * @param methodDuration Duration of the method in milliseconds.
     * @return A string representing message.
     */
    private static String buildLogMessage(String methodName, long methodDuration) {
        StringBuilder message = new StringBuilder();
        message.append("methodName --> ");
        message.append(methodName);
        message.append(" --> ");
        message.append("[");
        message.append(methodDuration);
        message.append("ms");
        message.append("]");

        return message.toString();
    }
}

然后在app中的某activity

...
    @DebugTrace
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_file_list);
...

即会打印出 I/* yang: Libraryaspectj –> onCreate –> [82ms]

以上就是对aspectj的简单实现后续展开都是遵循aspectj语法的使用

aspecjt文档

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值