AOP之Aspectj 使用

关于Aspectij 在android 中的使用

在 app目录下的bulid.gradle 文件中配置如下信息:

dependencies {
    ....
    //这样子不需要在lib 文件夹中引入jar 包
    compile 'org.aspectj:aspectjrt:1.9.2'
    //这种需要在lib 文件中放入jar包
    //compile file(libs/aspectjrt.jar)
}
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.9.2'
        classpath 'org.aspectj:aspectjweaver:1.9.2'
    }
}

repositories {
    mavenCentral()
}
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.9",
                         "-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
            }
        }
    }

如上配置完成,下面编写代码
新建注解类

 //表示方法上的注解
@Target(ElementType.METHOD)
//运行时注解
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckPerformance {
}

新建需要自定义行为的类

//注意需要加上 Aspect 注解
@Aspect
public class MethodBehaviorAspect {
    //新建方法 增加 Pointcut 注解 后面对应注解类的包名
    @Pointcut("execution(@com.lsghelper.Aspectj.CheckPerformance * *(..))")
    public void firstMethodAnnotationBehavior() {

    }

    //新建方法 增加 Around 注解 处理你想要的逻辑
    @Around("firstMethodAnnotationBehavior()")
    public Object CheckPerformance(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        //类名
        String simpleName = methodSignature.getDeclaringType().getSimpleName();
        //方法名
        String name = methodSignature.getName();
        CheckPerformance checkPerformance = methodSignature.getMethod().getAnnotation(CheckPerformance.class);
        long start = System.currentTimeMillis();
        //注意,调用这一句之后代表你注解的方法已经执行完成
        Object proceed = joinPoint.proceed();
        if (checkPerformance != null) {
            long end = System.currentTimeMillis();
            Log.e("TAG", "耗时: ---->" + (end - start));
        }
        return proceed;
    }
}

之后在对应的方法中使用注解

    @CheckPerformance
    public void hookHanlder() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
}

以上就是Aspectj 在android 中的使用方法。
至于其原理,和 ButterKnife 基本一致,主要在编译时修改增加了注解的对应的方法,自己拼接上我们写的逻辑,具体可以反编译 apk 查看可知。

你可能感兴趣的:(AOP之Aspectj 使用)