AOP: 切面编程框架:AspectJ (三)字节码分析

本文详细介绍了Android中如何集成AspectJ插件,并通过实际例子解析了AspectJ的语法,包括切点、切面、连接点、切入点和通知等概念。同时,展示了AspectJ在方法耗时统计和Systrace插桩中的应用场景,帮助理解AOP在Android开发中的应用。
摘要由CSDN通过智能技术生成

1:Android AspectJ 插件集成

1.1:AspectJ版本和 Gradle以及Gradle Tools 版本对应关系

GitHub - HujiangTechnology/gradle_plugin_android_aspectjx: A Android gradle plugin that effects AspectJ on Android project and can hook methods in Kotlin, aar and jar file.

2:AspectJ 语法解析

AspectJ 其实是一种 AOP框架,AOP是实现程序功能统一维护的一种技术,利用AOP可以对业务逻辑的各个部分进行隔离,从而使业务逻辑各部分之间的耦合性降低,提高程序的可重用性,提高开发效率。

2.1: 切点

切点表示对哪些方法进行拦截,拦截后怎么处理

2.2 :切面(Aspect)

类是对物体特征的抽象,切面就是对横切关注点的抽象

2.3:连接点(JoinPoint)

JPoint 是程序的关键执行点,也是我们关注的重点。它是指被拦截到的点(如方法、字段、构造器等)

2.4:切入点(PointCut)

对 JoinPoint进行拦截的定义,PointCut 的目的是提供一种方法使得开发者能够选择自己感兴趣的 JoinPoint

2.5:  通知(Advice)

切入点仅用于捕捉连接点集合,但是除了捕捉连接点集合外其他什么事情都没做,事实上实现横切行为我们需要使用通知,它一般指拦截到 JoinPoint 后需要执行的代码,分为前置,后置,环绕三种类型。

使用 PointCut 对我们指定的连接点进行拦截,通过 Advice ,就可以拦截到 JoinPoint后要执行的代码,Advice 通常有以下三种类型:

1)Before : PointCut 切点之前执行

2)After:   PointCut 切点之后执行

3)Around: PointCut 之前,之后分别执行

2.6: call 和 execution区别

execution(* android.app.Activity.on**(..))

上述表达式中:execution是一个匹配规则,第一个 * 代表匹配任意方法的返回值,后面语法表示匹配所有 Activity 中以 on开头的 方法,-----》这样我们就可以在 App 中所有 Activity中以 on开头的方法中输出一句log 

1)  call  : 代表调用方法的位置,插入在函数体外面

2)execution: 代表方法执行的位置,插入在函数体内部

3:分析AspectJ插桩字节码

3.1 先看如下插桩AspectJ类源码

@Aspect
public class TestAsject {

    // 定义切点
    @Pointcut("execution(* android.app.Activity+.onCreate(..))")
    public void activityOnCreate() {

    }

    /**
     *   环绕增强
     *    2022-05-07 16:40:05.714 16885-16885/? I/onCreateInjector: MainActivity: enter
     *    2022-05-07 16:40:05.823 16885-16885/? I/onCreate: enter
     * @param point
     */
    @Around("activityOnCreate()")
    public void onCreateInjector(ProceedingJoinPoint point) {
        Object object = point.getTarget();
        Log.i("TestAsject","onCreateInjector: "+ object.getClass().getSimpleName() + ": enter");
        try {
            point.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }

    /**
     * 前置增强
     * @param joinPoint
     */
    @Before("activityOnCreate()")
    public void onCreateBefore(JoinPoint joinPoint) {
        Log.i("TestAsject", "onCreateBefore: " + joinPoint.getSignature().getDeclaringType() + ":" + joinPoint.getSignature().getDeclaringTypeName());
    }

    /**
     * 后置增强
     * @param joinPoint
     */
    @After("activityOnCreate()")
    public void onCreateAfter(JoinPoint joinPoint) {
        Log.i("TestAsject", "onCreateAfter: " + joinPoint.getSignature().getDeclaringType() + ":"
                + joinPoint.getSignature().getDeclaringTypeName());
    }
}
public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i("TestAsject",": onCreate enter");
    }
}

打印内容:

1:  先打印连接点的 环绕通知

2:在打印且连接点的  Before通知

3:  然后打印 连接点的 切点

4:最后打印:连接带你的 After通知

2022-05-12 16:45:49.543 16056-16056/? I/TestAsject: onCreateAround: MainActivity: enter
2022-05-12 16:45:49.543 16056-16056/? I/TestAsject: onCreateBefore: class aop.yhw.com.aspectjproject.MainActivity:aop.yhw.com.aspectjproject.MainActivity
2022-05-12 16:45:49.649 16056-16056/? I/TestAsject: :MainActivity onCreate enter
2022-05-12 16:45:49.649 16056-16056/? I/TestAsject: onCreateAfter: class aop.yhw.com.aspectjproject.MainActivity:aop.yhw.com.aspectjproject.MainActivity

3.2:再看如下插桩AspectJ编译的字节码

4:AspectJ使用场景 

4.1 :统计Application中所有方法耗时

    @Aspect
    public class ApplicationAop {
    
        @Around("call (* com.json.chao.application.BaseApplication.**(..))")
        public void getTime(ProceedingJoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        String name = signature.toShortString();
        long time = System.currentTimeMillis();
        try {
            joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        Log.i(TAG, name + " cost" +     (System.currentTimeMillis() - time));
        }
    }

4.2: 对App 中所有的方法进行 Systrace函数插桩

查看应用中方法的耗时与 CPU 情况

    @Aspect
    public class SystraceTraceAspectj {

        private static final String TAG = "SystraceTraceAspectj";

        @Before("execution(* **(..))")
        public void before(JoinPoint joinPoint) {
            TraceCompat.beginSection(joinPoint.getSignature().toString());
        }
    
        @After("execution(* **(..))")
        public void after() {
            TraceCompat.endSection();
        }
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值