AspectJ介绍(一)

AOP概念

AOP是Aspect Oriented Programming的缩写,即『面向切面编程』。它和我们平时接触到的OOP都是编程的不同思想,OOP,即『面向对象编程』,它提倡的是将功能模块化,对象化,而AOP的思想,则不太一样,它提倡的是针对同一类问题的统一处理,当然,我们在实际编程过程中,不可能单纯的安装AOP或者OOP的思想来编程,很多时候,可能会混合多种编程思想,大家也不必要纠结该使用哪种思想,取百家之长,才是正道

AspectJ

AspectJ实际上是对AOP编程思想的一个实践,当然,除了AspectJ以外,还有很多其它的AOP实现,例如ASMDex,但目前最好、最方便的,依然是AspectJ。

发现问题

当初做自己的项目,有部分代码我不想让别人通过反编译知道其逻辑,我做过很多防护措施:

  1. 代码混淆
  2. 核心方法Native
  3. 动态加载dex,加载dex之前dex文件加密
  4. 动态加载so
  5. 所有声明字符串加密
  6. 使用3方加固平台(治标不治本)
  7. 插入代码花指令,jui工具编译方法报错

前面5要措施,都不是今天要讲的核心,其实第5条措施和今天说的有一些关联,但是实现逻辑原理是不一样的(不是今天的重点),说下第6条,对抗反编译其实就是对抗反编译工具,jadx丶jui都可以看代码,我发现有部分代码jui是编译出错的,这段代码在实际功能找中没有任何作用,但是插入这段代码jui工具就会编译出错,这就和花指令是一个到了,无效的代码,给**这带来难度,插入这代花指令代码,一开始我使用入侵的形式(其实就是手动复制粘贴),慢慢的核心方法越来越多,导致我阅读自己的代码都开始费劲了,学习了AspectJ,可以完美解决这个问题,废话不说开始

解决问题

  1. 当时我的方案是,通过ASM+Transformer库来完成这种逻辑,其实这种逻辑是可以实现的,我也能完成,但是在对ASM对class,由于我在方法内部插入的代码过多,ASM的class的字节码过于复杂,总是出错,开发成本非常高,上手难度很大,但是ASM库非常强大,更加灵活
  2. AsepcJ来解决(今天的主角),学习成本低,上手简单,完美解决问题

AspectJ的设计理念(概念)

Advice(通知)

注入到class文件中的代码。典型的 Advice 类型有 before、after 和 around,分别表示在目标方法执行之前、执行后和完全替代目标方法执行的代码。 除了在方法中注入代码,也可能会对代码做其他修改,比如在一个class中增加字段或者接口。

Joint point(连接点)

程序中可能作为代码注入目标的特定的点,例如一个方法调用或者方法入口。

Pointcut(切入点)

告诉代码注入工具,在何处注入一段特定代码的表达式。例如,在哪些 joint points 应用一个特定的 Advice。切入点可以选择唯一一个,比如执行某一个方法,也可以有多个选择,比如,标记了一个定义成@DebguTrace 的自定义注解的所有方法。

集成AspectJ

集成分为2种方法,建议插件集成

插件集成AspectJ

教程地址:https://github.com/HujiangTechnology/gradle_plugin_android_aspectjx

  1. 创建主项目app
  2. 创建library,AsepctJ
  3. 根目录的build.gradle,插入 classpath ‘com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.4’
  4. AsepctJ的build.gradle,依赖 api ‘org.aspectj:aspectjrt:1.8.9’
  5. App主项目,依赖 implementation project(’:aspectj’) ,应用plugin插件apply plugin: ‘com.hujiang.android-aspectjx’
    开源插件地址讲的很清楚,看下就会拉

gradle集成

教程地址:https://github.com/JakeWharton/hugo

来个简单demo爽一下

AspectJ介绍(一)
app就是需要主项目,aspectj就是需要做插代码的library,看了上面的方式应该都会集成好了AspectJ

代码

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        showMsg("我好牛B哦");
    }
    public void showMsg(String msg){
        Log.d("wyz", msg);
    }
}

AspectJ类

// 1:所需要插入代码的类,必须使用@Aspect注解
@Aspect
public class CoreAspetJ {
	// 需要注入的方法
    @After("call(* com.mmvoice.aspectjdemo.MainActivity.showMsg(java.lang.String))")
    public void showTaost(JoinPoint joinPoint) {
        Log.d("wyz", "AspectJ:牛B个锤子");
    }
}

运行效果

AspectJ介绍(一)
运行输入了这2句,我的代码showMsg只打印一个Log的

总结

这一章节,主要讲解了下集成方式,以及概念性的东西,以及我遇到的问题和解决问题的方式。