AOP(Aspect-Oriented Programming),即是面向切面编程,AspectJ是实现AOP的一个重要的框架,它是使用AspectJ编译器(ajc),在编译时期,在关键的的地方插入部分代码,处理相关逻辑,比如可以用于打印方法执行的效率,权限检查等。在Android上的应用主要是做性能监控、基于注解的数据埋点等, Hugo 就是基于AspectJ实现。
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' } 复制代码
用于打印日志
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface AspectDebugLog { } 复制代码
用于埋点
@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.class
可以看到通过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(); } } 复制代码