关于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 查看可知。