AOP(Aspect-Oriented Programming),便是面向切面編程,AspectJ是實現AOP的一個重要的框架,它是使用AspectJ編譯器(ajc),在編譯時期,在關鍵的的地方插入部分代碼,處理相關邏輯,好比能夠用於打印方法執行的效率,權限檢查等。在Android上的應用主要是作性能監控、基於註解的數據埋點等,Hugo 就是基於AspectJ實現。java
buildscript {
dependencies {
classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.0'
}
}
複製代碼
apply plugin: 'com.android.application'
apply plugin: 'android-aspectjx'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// 下面這行不是必須的,可是爲了有時候去掉上面插件不報錯就須要增長
implementation 'org.aspectj:aspectjrt:1.9.4'
}
複製代碼
用於打印日誌android
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AspectDebugLog {
}
複製代碼
用於埋點git
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AspectAnalyze {
String name();
}
複製代碼
@SuppressWarnings("unused")
@Aspect
public class AspectTrace {
private static AspectTraceListener aspectTraceListener;
/**
* 針對全部繼承 Activity 類的 onCreate 方法
*/
@Pointcut("execution(* android.app.Activity+.onCreate(..))")
public void activityOnCreatePointcut() {
}
/**
* 針對帶有AspectAnalyze註解的方法
*/
@Pointcut("execution(@com.taoweiji.aspect.trace.AspectAnalyze * *(..))")
public void aspectAnalyzeAnnotation() {
}
/**
* 針對帶有AspectDebugLog註解的方法
*/
@Pointcut("execution(@com.taoweiji.aspect.trace.AspectDebugLog * *(..))")
public void aspectDebugLogAnnotation() {
}
/**
* 針對前面 aspectAnalyzeAnnotation() 的配置
*/
@Around("aspectAnalyzeAnnotation()")
public void aroundJoinAspectAnalyze(final ProceedingJoinPoint joinPoint) throws Throwable {
Object target = joinPoint.getTarget();
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
AspectAnalyze aspectAnalyze = methodSignature.getMethod().getAnnotation(AspectAnalyze.class);
long startTimeMillis = System.currentTimeMillis();
joinPoint.proceed();
if (aspectTraceListener != null) {
aspectTraceListener.onAspectAnalyze(joinPoint, aspectAnalyze, methodSignature, System.currentTimeMillis() - startTimeMillis);
}
}
/**
* 針對前面 aspectDebugLogAnnotation() 或 activityOnCreatePointcut() 的配置
*/
@Around("aspectDebugLogAnnotation() || activityOnCreatePointcut()")
public void aroundJoinAspectDebugLog(final ProceedingJoinPoint joinPoint) throws Throwable {
long startTimeMillis = System.currentTimeMillis();
joinPoint.proceed();
long duration = System.currentTimeMillis() - startTimeMillis;
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
SourceLocation location = joinPoint.getSourceLocation();
String message = String.format("%s(%s:%s) [%sms]", methodSignature.getMethod().getName(), location.getFileName(), location.getLine(), duration);
if (aspectTraceListener != null) {
aspectTraceListener.logger("AspectTrace", message);
} else {
Log.e("AspectTrace", message);
}
}
public static void setAspectTraceListener(AspectTraceListener aspectTraceListener) {
AspectTrace.aspectTraceListener = aspectTraceListener;
}
public interface AspectTraceListener {
void logger(String tag, String message);
void onAspectAnalyze(ProceedingJoinPoint joinPoint, AspectAnalyze aspectAnalyze, MethodSignature methodSignature, long duration);
}
}
複製代碼
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
AspectTrace.setAspectTraceListener(new AspectTrace.AspectTraceListener() {
@Override
public void logger(String tag, String message) {
Log.e(tag, message);
}
@Override
public void onAspectAnalyze(ProceedingJoinPoint joinPoint, AspectAnalyze aspectAnalyze, MethodSignature methodSignature, long duration) {
Log.e("onAspectAnalyze", aspectAnalyze.name());
// TODO 實現統計功能
}
});
}
}
複製代碼
public class MainActivity extends Activity {
@AspectAnalyze(name = "MainActivity.onCreate")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.name).setOnClickListener(v -> onNameClick());
}
@AspectDebugLog
@AspectAnalyze(name = "onNameClick")
public void onNameClick() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@AspectAnalyze(name = "MainActivity.onDestroy")
@Override
protected void onDestroy() {
super.onDestroy();
}
}
複製代碼
E/onAspectAnalyze: MainActivity.onCreate
E/AspectTrace: onNameClick(MainActivity.java:28) [502ms]
E/onAspectAnalyze: onNameClick
E/onAspectAnalyze: MainActivity.onDestroy
複製代碼
app/build/intermediates/ajx/debug/includefiles/com/taoweiji/aspectjexample/MainActivity.classgithub
能夠看到經過AspectJ的ajc編譯器轉換後的class,在生成dex文件以前,在.class文件中插入了一些代碼,從而實現AOP技術。編程
public class MainActivity extends Activity {
public MainActivity() {
}
@AspectAnalyze(
name = "MainActivity.onCreate"
)
protected void onCreate(Bundle savedInstanceState) {
JoinPoint var3 = Factory.makeJP(ajc$tjp_0, this, this, savedInstanceState);
AspectTrace var10000 = AspectTrace.aspectOf();
Object[] var5 = new Object[]{this, savedInstanceState, var3};
var10000.aroundJoinAspectAnalyze((new MainActivity$AjcClosure3(var5)).linkClosureAndJoinPoint(69648));
}
@AspectDebugLog
@AspectAnalyze(
name = "onNameClick"
)
public void onNameClick() {
JoinPoint var2 = Factory.makeJP(ajc$tjp_1, this, this);
AspectTrace var10000 = AspectTrace.aspectOf();
Object[] var4 = new Object[]{this, var2};
var10000.aroundJoinAspectAnalyze((new MainActivity$AjcClosure7(var4)).linkClosureAndJoinPoint(69648));
}
@AspectAnalyze(
name = "MainActivity.onDestroy"
)
protected void onDestroy() {
JoinPoint var1 = Factory.makeJP(ajc$tjp_2, this, this);
AspectTrace var10000 = AspectTrace.aspectOf();
Object[] var2 = new Object[]{this, var1};
var10000.aroundJoinAspectAnalyze((new MainActivity$AjcClosure9(var2)).linkClosureAndJoinPoint(69648));
}
static {
ajc$preClinit();
}
}
複製代碼