工程下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'
- }
- // 标记这个类包括需要插入的代码和对应插入位置
- @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 编程指南文档,安卓具体用法会存在不同之处。
通过android提示transform的api,操作javac编译出字节码和jar引入的字节码。找到@Aspect标记的类,通过@Pointcut获得我们要插入方法的位置,@Before,@Around,@After标记的方法就是我们要插入的方法(@Aspect对应的类会改变成单例,就可以在对应的位置插入方法)。
主要分析方式通过查看操作的后的字节码,分析具体插入方法和实现方式
由于是基于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。往深的摸索就是字节码的生成,还有怎么编译的速度。