Android AspectJ简单使用

350 阅读2分钟

AOP

面向切面编程(AOP,Aspect-oriented programming):是一种可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的技术。AOP是OOP的延续,是软件开发中的一个热点,是函数式编程的一种衍生范型,将代码切入到类的指定方法、指定位置上的编程思想。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率

AspectJ

和Java语言无缝衔接的面向切面的编程的扩展工具(可用于Android)。

  1. 导入依赖

//1
     classpath 'org.aspectj:aspectjtools:1.9.6'
//2
     api 'org.aspectj:aspectjrt:1.9.6'
//3
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main

final def log = project.logger
//注意:如果是 Library Module 下面这个行代码中的 applicationVariants 应该替换为 libraryVariants
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.8",
                         "-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
            }
        }
    }
}
  1. 代码

自定义一个注解类 被添加注解的方法都可以显示log
@Retention(RetentionPolicy.RUNTIME)//在运行时编译
@Target({ElementType.METHOD})//作用在方法上
public @interface IsLoginInject {

    boolean value() default true;//是否开启显示日志

    LanguageEnum language() default LanguageEnum.CN_SIM;//显示日志的语言

}


public enum  LanguageEnum {
    CN_SIM,
    EN,
    JP
}



@Aspect  //Aspect注解
public class CusAspectJAnnotationBind {


    //@Around重写函数   execution 添加了@IsLoginInject方法在编译时执行该方法重写逻辑
    @Around("execution(@com.example.scrollviewd.ui.annotation.IsLoginInject * *(..))")
    public void aspectAnalyzeAnnotation(ProceedingJoinPoint joinPoint) {
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();


        String TAG=joinPoint.getTarget().getClass().getSimpleName();
        try {
            Method me = joinPoint.getTarget().getClass().getDeclaredMethod(ms.getName(), ms.getParameterTypes());
            
            
            IsLoginInject isLoginInject = me.getAnnotation(IsLoginInject.class);
            if (isLoginInject.value()) {
                if (AppDevice.getInstance().isLogin()) {
                    joinPoint.proceed();
                } else {
                    if (isLoginInject.language()==LanguageEnum.CN_SIM) {
                        Log.d(TAG, "账号未登录");
                    }else if (isLoginInject.language()==LanguageEnum.JP) {
                        Log.d(TAG, "アカウントが登録されていません");
                    }else if (isLoginInject.language()==LanguageEnum.EN) {
                        Log.d(TAG,
                                "Account not logged in");
                    }else{
                        Log.d(TAG,
                                "Error");
                    }

                }
            } else {
                joinPoint.proceed();//执行原来的代码
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }

    }
}

  1. 结果

AppDevice.getInstance().isLogin()==true?走原方法代码:拦截方法,不执行后面的代码,并打印日志