2018-08-19 AOP切面编程

仅仅当做笔记
最近学NDk学蒙蔽了,回过头来写Java感觉好幸福.


今天记录的是 AOP:

java --------> aspectj --------> class
在android 打包 .class转化成dex过程中,加入开发者定义的处理逻辑.

应用 转化成字节码文件之前,采用的是动态代理进行AOP切面的植入,比如用户行为统计,耗时操作的统计,集中式登录验证这些骚操作。

start 搬砖
step1: app 的build.gradle 加入

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

同样是 app的 build.gradle中(),(贴在最下面,不是在android&&dependencies中)


import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
//标注1
final def log = project.logger
final def variants = project.android.applicationVariants

variants.all { variant ->
    //标注2
    if (!variant.buildType.isDebuggable()) {
        log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")
        return;
    }
    //标注3
    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);
        //标注4
        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;
            }
        }
    }
}


!!! "最后记得要拷贝一个jar包"
叫做 aspectjir.jar到libs目录之下.

0怎么切入?
以这个注解为切入点,获取到属性,然后进行一系列的验证.
自定义注解 :
RetentionPolicy class和source
class 注解在class文件中有用,但会被VM丢弃.

比如ButterKnife的注解,作用的就是Class级别的文件
@Retention(CLASS) @Target(FIELD)
public @interface BindView {
/** View ID to which the field will be bound. */
@IdRes int value();
}

source 注解被编译器丢弃,仅仅存在于编译处理期间,编译器处理完成后就没有该注解了.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface BehaviorTrace {
String value();
}
统一的处理逻辑在哪里?

``
//这是一个切面
@Aspect
public class BehaviorTraceAspect {

//定义切面的规则 在原来应用中哪些注释的地方放到当前切面进行处理
@Pointcut("execution(@com.tianli.litemall.mytaskdemo.annotation.BehaviorTrace * *(..))")
public void analizyMethodBehaviorTrace() {
}


//获取到切面之后该如何进行处理
@Around("analizyMethodBehaviorTrace()")
public Object arroundJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
    MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
    //类名称
    String className = methodSignature.getDeclaringType().getSimpleName();//获取类名

//方法名称
String methodName = methodSignature.getName();
//注解中的属性
String funName = methodSignature.getMethod().getAnnotation(BehaviorTrace.class).value();

    long beginTime = System.currentTimeMillis();
    //这是切入点的方法的执行 start count time
    Object result = joinPoint.proceed();
    //结束的时间
    long endTime = System.currentTimeMillis();
    Log.d("Bob",String.format("%s类的 %s方法中的 %s功能执行总共耗费:%s 毫秒",className,methodName,funName,endTime - beginTime + ""));
    return result;
}

}
``

test code

    @BehaviorTrace("AsyncTask后台线程耗时时长")
        @Override
        protected String doInBackground(Void... voids) {
            Log.d("TAGHS", "当前的线程:\n"+Thread.currentThread().getName());
            for (int i = 0; i < 100; i++) {
                SystemClock.sleep(10);
                publishProgress(i);
            }
            return null;

        }

你可能感兴趣的:(2018-08-19 AOP切面编程)