安装AspectJ

Pangu-Immortal (Pangu-Immortal) · GitHub

Android上的ApsectJ开发由几部分组成,AspectJ gradle插件,ApsectJ依赖,还有 AspectJ编译器。
首先安装AspectJ编译器很简单,就跟安装JAVA环境一样,
下载链接:http://www.eclipse.org/downloads/download.php?file=/tools/aspectj/aspectj-1.9.0.jar
目前最新的已经更新到1.9.1了。如果你电脑已经有JAVA环境的话直接运行这个jar包就行,
在安装完毕后需要配置环境变量到 aspectj的bin目录下,这里不赘述

export PATH="$PATH:~/Library/Android/sdk/platform-tools"
export PATH="$PATH:/usr/local/opt/gradle/gradle-4.1/bin"
export PATH="$PATH:~/Library/Android/sdk/ndk-bundle"
export PATH="$PATH:~/Library/flutter/bin"
export PATH="$PATH:~/Library/kotlinc/bin"
export PATH="$PATH:~/Library/AspectJ/bin" <- AspectJ的PATH
配置完后运行 ajc -v 应该可以看到对应输出

AspectJ Compiler 1.9.1 (1.9.1 - Built:  2018 at 17:52:10 GMT)

赠送源码:https://github.com/Pangu-Immortal。

《最完整的Android逆向知识体系》


配置Android Gradle增加AspectJ依赖

首先需要把 AspectJ 依赖加到 gradle根目录中,

buildscript {repositories {maven { url 'https://maven.google.com' }maven { url 'https://jitpack.io' }jcenter()google()mavenCentral()}dependencies {classpath 'com.android.tools.build:gradle:3.2.1'classpath 'org.aspectj:aspectjtools:1.9.1'classpath 'org.aspectj:aspectjweaver:1.9.1'}
}

然后在项目app目录的build.gradle需要添加以下内容,

import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Mainapply plugin: 'com.android.application'android {...compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}
}dependencies {implementation fileTree(include: ['*.jar'], dir: 'libs')implementation 'org.aspectj:aspectjrt:1.9.1'
}final def log = project.logger
final def variants = project.android.applicationVariants
variants.all { variant ->if (!variant.buildType.isDebuggable()) {log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")return}JavaCompile javaCompile = variant.javaCompilejavaCompile.doLast {String[] args = ["-showWeaveInfo","-1.8","-inpath", javaCompile.destinationDir.toString(),"-aspectpath", javaCompile.classpath.asPath,"-d", javaCompile.destinationDir.toString(),"-classpath", javaCompile.classpath.asPath,"-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]log.debug "ajc args: " + Arrays.toString(args)MessageHandler handler = new MessageHandler(true)new Main().run(args, handler)for (IMessage message : handler.getMessages(null, true)) {switch (message.getKind()) {case IMessage.ABORT:case IMessage.ERROR:case IMessage.FAIL:log.error message.message, message.thrownbreakcase IMessage.WARNING:log.warn message.message, message.thrownbreakcase IMessage.INFO:log.info message.message, message.thrownbreakcase IMessage.DEBUG:log.debug message.message, message.thrownbreak}}}
}

创建AspectJ代码

下面这部分代码看起来会一脸懵逼,不过目前先不用管具体的语法含义,
先跑起来环境,然后再结合理论慢慢在修改代码中感受就能快速的上手AOP了。
以一个HelloWorld为例子,我们的MainActivity中啥事情不干,只有基本的生命周期方法。

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}@Overrideprotected void onStart() {super.onStart();}
}

现在我们要写一个AspectJ类。
这个类要做的事情是告诉ACJ编译器,要在MainActivity中的每个方法前面打印一行log,输出当前执行的是哪个方法,

@Aspect
public class AspectTest {@Pointcut("execution(* phoenix.com.helloaspectj.MainActivity.**(..))")public void executeAspectJ() {} // 注意*号后面必须有空格@Before("executeAspectJ()")public void beforeAspectJ(JoinPoint joinPoint) throws Throwable  {Log.d(”tag“, "injected -> " + joinPoint.toShortString());}
}

第一次接触AspectJ的看到这段代码有点摸不着头脑,解释一下几个注解的意思,
@Aspect: 告诉ACJ编译器这是个AspectJ类
@PointCut: PointCut是AspectJ中的一个概念,跟它一起的另一个概念是 JoinPoint,这两个概念一起描述要注入的切面
@Before: 表示要注入的位置,常用的有 Before/After/Around,分别表示在执行前,执行后,和取代原方法

这里@PointCut注解后的参数表示的意思是对 MainActivity中的所有方法进行注入,参数用的是正则匹配语法。
下面看看这段代码执行的结果

16:04:56.611 22823-22823/? D/tag: injected -> execution(MainActivity.onCreate(..))
16:04:56.661 22823-22823/? D/tag: injected -> execution(MainActivity.onStart())

看到虽然我们没有在MainActivity中写入log打印语句,但是通过AspectJ实现了,在MainActivity两个生命周期执行前插入了我们自己的log。

严格的说使用方式有两种,随便网上搜一下都能找到,例子就不多举了,随便体验一个简单,有了直接的感受就好。

本篇主要目的还是让新手快速上手并亲身体会,关键 让你知道我们开发的时候用AspectJ来干点啥。。

(知识点很简单,主要还是消除大家心里的疑惑,带着疑惑很难接受新知识)---这也是我的一个学习方法。


Pointcuts 示例

以下示例表示在aspectjx插件下,相同包是指同一个aar/jar包,AspectJ常规配置下不同包不能执行“execution”织入

execution

execution(* com.howtodoinjava.EmployeeManager.*( .. ))
    匹配EmployeeManger接口中所有的方法
    execution(* EmployeeManager.*( .. ))
    当切面方法和EmployeeManager接口在相同的包下时,匹配EmployeeManger接口中所有的方法
    execution(public * EmployeeManager.*(..))
    当切面方法和EmployeeManager接口在相同的包下时,匹配EmployeeManager接口的所有public方法
    execution(public EmployeeDTO EmployeeManager.*(..))
    匹配EmployeeManager接口中权限为public并返回类型为EmployeeDTO的所有方法。
    execution(public EmployeeDTO EmployeeManager.*(EmployeeDTO, ..))
    匹配EmployeeManager接口中权限为public并返回类型为EmployeeDTO,第一个参数为EmployeeDTO类型的所有方法。
    execution(public EmployeeDTO EmployeeManager.*(EmployeeDTO, Integer))
    匹配EmployeeManager接口中权限为public、返回类型为EmployeeDTO,参数定义为EmployeeDTO,Integer的所有方法。
    "execution(@com.xyz.service.BehaviorTrace * *(..))"
    匹配注解为"@com.xyz.service.BehaviorTrace",返回值为任意类型,任意包名下的任意方法。

within

任意连接点:包括类/对象初始化块,field,方法,构造器

within(com.xyz.service.*)
    com.xyz.service包下任意连接点
    within(com.xyz.service..*)
    com.xyz.service包或子包下任意连接点
    within(TestAspect)
    TestAspect类下的任意连接点
    within(@com.xyz.service.BehavioClass *)
    持有com.xyz.service.BehavioClass注解的任意连接点

主要应用场景:(重点)

  • 数据统计
  • 日志记录
  • 用户行为统计
  • 应用性能统计
  • 数据校验
  • 行为拦截
  • 无侵入的在宿主中插入一些代码,
  • 做日志埋点
  • 性能监控
  • 动态权限控制
  • 代码调试

AspectJ 只是 AOP 的一种手段,类似的还有用 asm 去修改字节码。

AOP之所以会有越来越多的人去了解。

  • 第一,非常好的去耦合。
  • 第二,可以用AOP来实现无痕埋点,数据收集,甚至修改SDK中动不了的代码。

暂不支持 Java 9 以上平台

其他问题请看插件的文档和 Issues。

赠送源码:https://github.com/Pangu-Immortal。

《最完整的Android逆向知识体系》

Android面向切面编程框架(AspectJ 讲解)相关推荐

  1. Android 面向切面编程(AOP)

    概念: AOP: Aspect Oriented Programming 面向切面编程. AOP是个概念,AspectJ 是它的一个具体实现.和Java配合使用. AspectJ:核心是他的编译器(a ...

  2. Android 面向切面编程-aspjectj应用

    先附上自己基于aspject封装的aop 插件 1.为什么要用切面 随着业务越来越复杂,项目中的模块可能越来越多, 面向切面可以减少模块间的耦合,提高模块的复用率 2.aspjectj语法 andro ...

  3. 面向切面编程AspectJ在Android埋点的实践

    在项目开发中,对 App 客户端重构后,发现用于统计用户行为的友盟统计代码和用户行为日志记录代码分散在各业务模块中,比如在某个模块,要想实现对用户的行为一和行为二进行统计,因此按照OOP面向对象编程思 ...

  4. 【AOP 面向切面编程】Android Studio 使用 AspectJ 监控方法运行原理分析

    文章目录 一.查看使用 AspectJ 后生成的 Class 字节码类 二.AspectJ 的本质 一.查看使用 AspectJ 后生成的 Class 字节码类 在 Android Studio 中查 ...

  5. 【AOP 面向切面编程】Android Studio 中配置 AspectJ ( 下载并配置AS中 jar 包 | 配置 Gradle 和 Gradle 插件版本 | 配置 Gradle 构建脚本 )

    文章目录 一.AspectJ 下载 二.拷贝 aspectjrt.jar 到 Android Studio 三.配置 Gradle 和 Gradle 插件版本 四.配置 Gradle 构建脚本 一.A ...

  6. Android面向切面(AOP)编程实战

    转载自https://www.jianshu.com/p/b96a68ba50db AOP:面向切面编程(Aspect-Oriented Programming).如果说,OOP如果是把问题划分到单个 ...

  7. Android AOP 面向切面编程

    一.AOP即面向切面编程 AOP 是 Aspect Oriented Programming 的缩写,译为面向切面编程.用我们最常用的 OOP 来对比理解: 纵向关系 OOP,横向角度 AOP 举个例 ...

  8. Android——面向AOP编程(二) Xerath 开源AOP框架

    承接上文Android--面向AOP编程(一)https://pumpkin.blog.csdn.net/article/details/119849325https://pumpkin.blog.c ...

  9. 【SSM框架系列】Spring 的 AOP(面向切面编程)

    什么是 AOP AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP 是 OOP ...

最新文章

  1. 使用jpmml-sparkml-executable生成PMML模型文件
  2. Surf算法学习心得(一)——算法原理
  3. ViewTreeObserver
  4. Android自制SwitchBar(附资源)
  5. 建筑工程项目管理信息化PM
  6. 让UILabel的文字顶部对齐
  7. python二维列表的展开_python将三维数组展开成二维数组的实现
  8. java代码获取数据源_tomcat中获取不同的数据源java代码
  9. php用空格分隔字符串,分割字符串空格
  10. 软件工程 超市库存管理系统 UML模型
  11. 大学计算机应用基础教学设计,大学计算机应用基础电子教案设计.doc
  12. 随机分组c语言,用C/C++进行随机分组的实现教程,分组教程
  13. Python中文分词库jieba用法代码示例
  14. 网站投票系统制作与流程
  15. 年薪40-80K *14 | 网境科技SLAM算法工程师、算法科学家招聘
  16. excel单元格斜杠拆分上下打字
  17. 2C+1A(JD6621*2PCS+FP6601A)智能退功率实现方案
  18. 【Hyper-V】Windows10家庭版安装Hyper-V虚拟机
  19. 进度管理PV,AC,EV
  20. matlab编程与最优化设计应用,MATLAB编程与最优化设计应用

热门文章

  1. CF452F Permutations/Luogu2757 等差子序列 树状数组、Hash
  2. 4.类型设计规范《.NET设计规范》
  3. Web 之困 现代Web应用安全指南一本好书 69.00?
  4. sharepoint 2010项目中,ashx页面获取SPContext.Current 为null的原因和解决方法
  5. size()函数的使用
  6. sql 2008 R2添加对MySql的远程服务器链接
  7. [Innost]Android深入浅出之Binder机制
  8. [转]JavaScript var obj = { id:1, name:jacky } 大括号是啥意思?
  9. SQL Server数据库查询区分大小写、全半角——排序规则的应用(转载)
  10. D04——C语言基础学PYTHON