使用AspectJ,需要用到它提供的注解:
还有就是最后一步,具体处理方法使用的注解:
AspectJ是一个客户端,拥有自己的编译器,所以要在Gradle中指定,使用AspectJ的编译器进行编译
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.aspectj:aspectjtools:1.9.6'
classpath 'org.aspectj:aspectjweaver:1.9.6'
}
}
plugins {
id 'com.android.application'
}
...
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;
}
}
}
}
下载地址:https://gitee.com/aruba/aopapplication/blob/master/app/libs/aspectjrt.jar
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.aspectj:aspectjtools:1.9.6'
classpath 'org.aspectj:aspectjweaver:1.9.6'
}
}
plugins {
id 'com.android.application'
}
android {
compileSdk 30
defaultConfig {
applicationId "com.aruba.aopapplication"
minSdk 21
targetSdk 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
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;
}
}
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation files('libs\\aspectjrt.jar')
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
/**
* 用于注解点
* Created by aruba on 2021/11/1.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BehaviorTrace {
String value();
}
首先使用Aspect注解类,再通过Pointcut注解指定该切面中的点(这边就是方法),最后使用Around注解来替换原来的方法执行
/**
* Created by aruba on 2021/11/1.
*/
@Aspect
public class AspectBehavior {
//指定使用BehaviorTrace注解的所有包下所有类的所有方法,为一个切面
@Pointcut("execution(@com.aruba.aopapplication.annotations.BehaviorTrace * *(..))")
public void methodAnnotatedWithBehaviorTrace() {
}
//争对上面切面methodAnnotatedWithBehaviorTrace的所有点进行处理
@Around("methodAnnotatedWithBehaviorTrace()")
public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) {
Object ret = null;
try {
//获取方法签名
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
//获取注解
BehaviorTrace annotation = methodSignature.getMethod().getAnnotation(BehaviorTrace.class);
//执行之前记录下时间
long startTime = System.currentTimeMillis();
//方法执行
ret = joinPoint.proceed();
//方法执行完后的耗时
long diffTime = System.currentTimeMillis() - startTime;
String clzName = methodSignature.getDeclaringType().getSimpleName();
String methodName = methodSignature.getName();
Log.d("aruba", String.format("功能:%s 类:%s中方法:%s执行耗时:%d ms", annotation.value(), clzName, methodName, diffTime));
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return ret;
}
}
注解方法就是表示该方法为一个点
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@BehaviorTrace("上传")
public void upload(View view) {
SystemClock.sleep(300);
}
@BehaviorTrace("下载")
public void download(View view) {
SystemClock.sleep(400);
}
@BehaviorTrace("扫码")
public void scan(View view) {
SystemClock.sleep(500);
}
}
三个按钮点击后的日志如下: