仅仅当做笔记
最近学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;
}
网友评论