AOP(Aspect-Oriented Programming), 即是面向切面编程, AspectJ 是实现 AOP 的一个重要的框架, 它是使用 AspectJ 编译器 (ajc), 在编译时期, 在关键的的地方插入部分代码, 处理相关逻辑, 比如可以用于打印方法执行的效率, 权限检查等. 在 Android 上的应用主要是做性能监控, 基于注解的数据埋点等, Hugo 就是基于 AspectJ 实现.
教程
修改项目根目录的 build.gradle 文件
- buildscript {
- dependencies {
- classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.0'
- }
- }
在 App 和 Module 的 build.gradle 增加插件
- 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);
- }
- }
配置
在 MyApplication 设置监听器
- 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();
- }
- }
来源: http://www.jianshu.com/p/fb8d832e0dfd