官方参考
https://github.com/HujiangTechnology/gradle_plugin_android_aspectjx
AOP 切片编程 SDK使用
- build.gradle
buildscript {
repositories {
mavenLocal()
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
// 沪江网AOP插件,使用比较简单
classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.8'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
- app/build.gradle
apply plugin: 'com.android.application'
apply plugin: 'android-aspectjx'
android {
compileSdkVersion 29
buildToolsVersion '26.0.2'
defaultConfig {
// 省略...
}
buildTypes {
// 省略...
}
// 省略...
aspectjx {
enabled true //关闭AspectJX功能。开关控制
}
}
- app/proguard-rules.pro
# 保持泛型不被混淆
-keepattributes Signature
# 保留所有注解,避免混淆时,注解丢失
-keepattributes *Annotation*
-keep class * extends java.lang.annotation.Annotation { *; }
# 不混淆使用了注解的类及类成员
-keep @com.aop.test.Timer class * {*;}
# 如果类中有使用了注解的方法,则不混淆类和类成员
-keepclasseswithmembers class * {
@com.aop.test.Timer <methods>;
}
# 如果类中有使用了注解的字段,则不混淆类和类成员
-keepclasseswithmembers class * {
@com.aop.test.Timer <fields>;
}
# 如果类中有使用了注解的构造函数,则不混淆类和类成员
-keepclasseswithmembers class * {
@com.aop.test.Timer <init>(...);
}
# AspectJ注解引用的对象必须被keep。比如注解的函数的入参类
-keep class com.aop.test.Device
- com/aop/test/Timer.java 注解类
package com.aop.test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 定义注解
*
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Timer {
String value() default "";
}
- com/aop/test/ConnectionAspect.java 切片类
package com.aop.test;
import android.text.TextUtils;
import android.util.Log;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* 当注解的函数的参数中包含自定义对象时,该对象不能被混淆,否则{@link MethodSignature#getMethod()}方法无法获取函数对象。
*
* @since 2021-02-24
*/
@Aspect
public class ConnectionAspect {
private static final String TAG = "ConnectionAspect";
@Pointcut("execution(@com.aop.test.Timer * *(..))")
public void method() {
}
@Before("method()")
public void record(JoinPoint joinPoint) throws Throwable {
if (Objects.isNull(joinPoint) || Objects.isNull(joinPoint.getSignature()) || !(joinPoint.getSignature() instanceof MethodSignature)) {
return;
}
long startTime = System.currentTimeMillis();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Log.v(TAG, "joinPoint signature name " + signature.getName() + ", class " + signature.getDeclaringTypeName());
Method method = signature.getMethod();
if (Objects.isNull(method)) {
Log.e(TAG, signature.getName() + " method is null");
return;
}
Timer timer = method.getAnnotation(Timer.class);
if (Objects.isNull(timer)) {
Log.e(TAG, signature.getName() + " timer is null");
return;
}
map.put(timer.value(), startTime);
}
}
AOP报错ProceedingJoinPoint is only supported for around advice
- 这是因为在返回后通知(@AfterReturning)和抛出异常后通知(@AfterThrowing)的方法中不能使用ProceedingJoinPoint,使用JoinPoint即可解决.
- @Before 和 @After入参是JoinPoint,不是 ProceedingJoinPoint
- 报错如下
> Task :app:transformClassesWithDesugarForRelease
:app:transformClassesWithDesugarForRelease spend 2245ms
use of ProceedingJoinPoint is allowed only on around advice (arg 0 in (before(extraFlags: 2): (execution(@com.huawei.sinktester.chenggong.Timer * *(..)) && persingleton(com.huawei.sinktester.chenggong.TimerRecord))->void com.huawei.sinktester.chenggong.TimerRecord.record(org.aspectj.lang.ProceedingJoinPoint)))
use of ProceedingJoinPoint is allowed only on around advice (arg 0 in (before(extraFlags: 2): (execution(@com.huawei.sinktester.chenggong.Timer * *(..)) && persingleton(com.huawei.sinktester.chenggong.TimerRecord))->void com.huawei.sinktester.chenggong.TimerRecord.record(org.aspectj.lang.ProceedingJoinPoint)))
混淆时,需要配置
- 不混淆使用了注解的类及类成员
-keep @com.pang.view.base.annotation.ViewInject class * {*;} - 如果类中有使用了注解的方法,则不混淆类和类成员
-keepclasseswithmembers class * {
@com.pang.view.base.annotation.ViewInject ;
} - 如果类中有使用了注解的字段,则不混淆类和类成员
-keepclasseswithmembers class * {
@com.pang.view.base.annotation.ViewInject ;
} - 如果类中有使用了注解的构造函数,则不混淆类和类成员
-keepclasseswithmembers class * {
@com.pang.view.base.annotation.ViewInject (…);
} - The “Signature” attribute is required to be able to access generic types whencompiling in JDK 5.0 and higher.
-keepattributes Signature - processing Annotations
-keepattributes Annotation