Aspectj基础原理解析

一、接入和使用

1、依赖导入

工程下gradle下

buildscript{
  
    dependencies {

        // 用于导入aspectj的plugin
        classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.8'
    }
}

对应app或者module的gradle下

// 在当前模块应用aspectj实现字节码插桩
apply plugin: 'android-aspectjx'

// 常用排除一些目录下的代码
aspectjx {
    exclude 'versions.9', 'androidx', 'com.google', 'com.taobao', 'com.ut'
}

dependencies {

    // 主要导入对应注解和一些通用模板代码
    implementation 'org.aspectj:aspectjrt:1.8.9'
}

2、基础使用(仅简单例子)

// 标记这个类包括需要插入的代码和对应插入位置
@Aspect
public class Aspectj {
    
    // 指定对应的切入点
    @Pointcut("execution(* android.com.aspectj.BaseActivity+.onCreate(..)) && within(android.com.aspectj.MainActivity)")
    public void activityOnCreatePointcut() {

    }

    // 在该方法执行前插入
    @Before("activityOnCreatePointcut()")
    public void activityOnCreateBefore(JoinPoint joinPoint) {
        Log.d("xx", "activityOnCreateBefore: " + joinPoint.getThis());
    }

    // 增强的插入方法
    @Around("activityOnCreatePointcut()")
    public void activityOnCreateAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Log.d("xx", "activityOnCreateAround: " + joinPoint.getThis());
        joinPoint.proceed();
    }

    // 如果After和Around同时存在,After必须在Around之后
    @After("activityOnCreatePointcut()")
    public void activityOnCreateAfter(JoinPoint joinPoint) {
        Log.d("xx", "activityOnCreateAfter: " + joinPoint.getThis());
    }

}

按照Aspectj定下规则,就是可以编写出想要在哪里插入想要的代码,具体的规则说明就不详细的描述了,可以参照AspectJTM 编程指南文档,安卓具体用法会存在不同之处。

二、基础原理说明

1、大体的原理

通过android提示transform的api,操作javac编译出字节码和jar引入的字节码。找到@Aspect标记的类,通过@Pointcut获得我们要插入方法的位置,@Before,@Around,@After标记的方法就是我们要插入的方法(@Aspect对应的类会改变成单例,就可以在对应的位置插入方法)。

2、解析具体的注解和关键字

主要分析方式通过查看操作的后的字节码,分析具体插入方法和实现方式

由于是基于transform的api,可以在Transform的目录找到其加过后的代码

 (1) 使用execution在对应的方法内插入代码配合@Before @After

    @Pointcut("execution(* android.com.aspectj.BaseActivity+.onCreate(..)) && within(android.com.aspectj.MainActivity)")
    public void activityOnCreatePointcut() {

    }

    @Before("activityOnCreatePointcut()")
    public void activityOnCreateBefore(JoinPoint joinPoint) {
        Log.d("xx", "activityOnCreateBefore: " + joinPoint.getThis());
    }

 (2)使用call在对应方法调用插入代码配合@Before @After

   @Pointcut(
        "call(* com.example.app1.TextAspectjCall.call()) && withincode(* com.example.app1.MainActivity.onCreate(..))")
    public void callPointcut() {

    }

    @Before("callPointcut()")
    public void call(JoinPoint joinPoint) {
        Log.d("xx", "callBefore(call): " + joinPoint.getThis());
    }

 (3)@Around增强版的方法插入

1、配合execution

生成一个新方法,插入相关代码,放入原先的方法中调用

   @Pointcut("execution(* com.example.app1.BaseActivity+.onCreate(..)) && within(com.example.app1.MainActivity)")
    public void activityOnCreatePointcut() {

    }

    @Around("activityOnCreatePointcut()")
    public void activityOnCreateAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Log.d("xx", "activityOnCreateAround: " + joinPoint.getThis());
        joinPoint.proceed();
    }

 2、配合call

在调用处,形成一个新的方法,在这个方法内插入代码,通过调用这个方法,就实现了在调用处实现使用这个@Around插入代码

    @Pointcut("call(* com.example.app1.TextAspectjCall.callWithReturn())")
    public void callWithReturn() {

    }

    @Around("callWithReturn()")
    public Object call2(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long duration = System.currentTimeMillis() - start;
        Log.d("xx", "callWithReturn" + duration);
        return result;
    }

 以上就是常用4种方案的解析

三、总结

Aspectj的基本用法没有什么难度,基本原理也是基于transform api。往深的摸索就是字节码的生成,还有怎么编译的速度。

示例代码

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值