一、首先说说使用AspectJ的意义
使用切点插入,减少冗余代码,但是因为是编译时插入,所以运行时会有性能损耗,但是总的来说微乎其微
二、运行原理
这是我原来的代码
@BehaviorTrace("点击方法")
public void test(){
SystemClock.sleep(3000);
Toast.makeText(MainActivity.this, "hahha", Toast.LENGTH_SHORT).show();
}
这是运行编译后的代码
@BehaviorTrace("点击方法")
public void test() {
JoinPoint var1 = Factory.makeJP(ajc$tjp_0, this, this);
BehaviorAspect var10000 = BehaviorAspect.aspectOf();
Object[] var2 = new Object[]{this, var1};
var10000.waveJoinPoint((new MainActivity$AjcClosure1(var2)).linkClosureAndJoinPoint(69648));
}
他是在对应切点插入插入代码,然后使用Aspectj的规则去编译运行
二、实现
我是直接放在一个model下的,没用新建model你也可以新建一个model
1、首先在项目的gradle文件中引入
classpath 'org.aspectj:aspectjtools:1.8.9'
classpath 'org.aspectj:aspectjweaver:1.8.9'
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.4'
classpath 'org.aspectj:aspectjtools:1.8.9'
classpath 'org.aspectj:aspectjweaver:1.8.9'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
2、在app下的gradle文件中引入AspectJrt文件,和编译替换文件
implementation 'org.aspectj:aspectjrt:1.8.9'
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
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.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;
}
}
}
}
以上就配置好了编译环境,接下来是使用AspectJ
1、先创建注解文件
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BehaviorTrace {
String value();
}
2、创建AOP文件,并实现
@Aspect
public class BehaviorAspect {
//切点,执行com.xiaofan.customcontrol.annotation.BehaviorTrace路径下的注解
@Pointcut("execution(@com.xiaofan.customcontrol.annotation.BehaviorTrace * *(..))")
public void annoBaviorTrace() {}
//执行annoBaviorTrace方法
@Around("annoBaviorTrace()")
public Object waveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
BehaviorTrace anno = methodSignature.getMethod().getAnnotation(BehaviorTrace.class);
String functionName = anno.value();
Log.i("wxf","方法:"+functionName);
long begin = System.currentTimeMillis();
//方法执行
Object reuslt= joinPoint.proceed();
long duration = System.currentTimeMillis() - begin;
Log.i("wxf","方法耗时:"+duration+" ms");
return reuslt;
}
}
最后使用,在你需要使用的地方直接添加注解即可,
以上就是一个简单的AspectJ使用案例,当然它能做的事情不知这一点
注意:我也试过全使用jar包,但是在gradle替换代码中,找不到包