referencia oficial
https://github.com/HujiangTechnology/gradle_plugin_android_aspectjx
Uso del SDK de programación de sectores AOP
- construir.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()
}
}
- aplicación/build.gradle
apply plugin: 'com.android.application'
apply plugin: 'android-aspectjx'
android {
compileSdkVersion 29
buildToolsVersion '26.0.2'
defaultConfig {
// 省略...
}
buildTypes {
// 省略...
}
// 省略...
aspectjx {
enabled true //关闭AspectJX功能。开关控制
}
}
- aplicación/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 clase de anotación
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 clase de segmento
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 solo se admite para consejos aproximados
- Esto se debe a que ProceedingJoinPoint no se puede utilizar en los métodos de notificación posterior a la devolución (@AfterReturning) y notificación de excepción posterior al lanzamiento (@AfterThrowing), y se puede resolver mediante JoinPoint.
- Los parámetros de entrada @Before y @After son JoinPoint, no ProceedingJoinPoint
- El error se informa de la siguiente manera.
> 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)))
Al ofuscar, se requiere configuración
- No confunda clases anotadas y miembros de clase:
mantenga @com.pang.view.base.annotation.ViewInject class * {*;} - Si hay métodos anotados en la clase, la clase y los miembros de la clase no se confundirán
-keepclasseswithmembers class * { @com.pang.view.base.annotation.ViewInject; } - Si hay campos anotados en la clase, no confunda la clase y los miembros de la clase
-keepclasseswithmembers class * { @com.pang.view.base.annotation.ViewInject; } - Si hay un constructor anotado en la clase, la clase y los miembros de la clase no se confundirán
-keepclasseswithmembers class * { @com.pang.view.base.annotation.ViewInject (…); } - El atributo "Firma" es necesario para poder acceder a tipos genéricos al compilar en JDK 5.0 y superior.
-keepattributes Firma - Procesando anotaciones
- Keepattributes Anotación