版权声明:本文为博主原创文章,未经博主允许不得转载。

转载请表明出处:http://www.cnblogs.com/cavalier-/p/8888459.html

什么是AOP

AOP是 Aspect Oriented Programming 的缩写,即面向切面编程,和平常遇到的面向对象OOP编程不一样的是,OOP是将功能模块化对象化,AOP是针对同一类的问题统一化处理。例如做日志埋点,性能监控,动态权限控制等。

AspectJ

AspectJ实际上是对AOP编程的实践,目前还有很多的AOP实现,如ASMDex,但笔者选用的是AspectJ。

在Android项目中使用AspectJ

如果使用原生AspectJ在项目中配置会非常麻烦,在GitHub上有个开源的SDK gradle_plugin_android_aspectjx基于gradle配置即可。

接入说明

请自行查看开源项目中的接入配置过程

AspectJ 之 Join Points介绍

Join Points在AspectJ中是关键的概念。Join Points可以看做是程序运行时的一个执行点,比如:一个函数的调用可以看做是个Join Points,相当于代码切入点。但在AspectJ中,只有下面几种执行点是认为是Join Points:

Join Points 说明 实例
method call 函数调用 比如调用Log.e(),这是一个个Join Point
method execution 函数执行 比如Log.e()的执行内部,是一处Join Points。注意这里是函数内部
constructor call 构造函数调用 和method call 类似
constructor execution 构造函数执行 和method execution 类似
field get 获取某个变量 比如读取DemoActivity.debug成员
field set 设置某个变量 比如设置DemoActivity.debug成员
pre-initialization Object在构造函数中做的一些工作。 -
initialization Object在构造函数中做的工作。 -
static initialization 类初始化 比如类的static{}
handler 异常处理 比如try catch 中,对应catch内的执行
advice execution 这个是AspectJ 的内容 -

Pointcuts 介绍

一个程序会有多个Join Points,即使同一个函数,也还分为call 和 execution 类型的Join Points,但并不是所有的Join Points 都是我们关心的,Pointcuts 就是提供一种使得开发者能够值选择所需的JoinPoints的方法。

Advice

Advice就是我们插入的代码可以以何种方式插入,有Before 还有 After、Around。
下面看个例子:

@Before(“execution(* android.app.Activity.on**(..)))”)
public void onActivityMethodBefore(JoinPoint joinPoint) throws Throwable{
}

这里会分成好几个部分,我们依次来看:

  • @Before: Advice, 也就是具体的插入点
  • execution:处理Join Point的类型,例如call、execution
  • (* android.app.Activity.on**(..)): 这个是最重要的表达式,第一个*表示返回值,*表示返回值为任意类型,后面这个就是典型的包名路径,其中可以包含 *来进行通配,几个 *没有区别。同时这里可以通过&&、||、!来进行条件组合。()代表这个方法的参数,你可以指定类型,例如android.os.Bundle,或者 (..) 这样来代表任意类型、任意个数的参数。
  • public void onActivityMehodBefore: 实际切入的代码。

Before 和 After 其实还是很好理解的,也就是在Pointcuts之前和之后,插入代码,那么Android呢,从字面含义上来讲,也就是在方法前后各插入代码,他包含了 Before和 After 的全部功能,代码如下:

@(“execution(* com.xys.aspectjxdemo.MainActivity.testAOP()))”)
public void onActivityMethodAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{String key = proceedingJoinPoint.getSignature().toString();Log.d(TAG,”onActivityMethodAroundFirst:”+key);proceedingJoinPoint.proceed();Log.d(TAG,”onActivityMethodAroundSecond:”+key);
}

以上代码中,proceedingJoinPoint.proceed()代表执行原始的方法,在这之前、之后,都可以进行各种逻辑处理。

自定义Pointcuts

自定义Pointcuts可以让我们更加精准的切入一个或多个指定的切入点。
首先我们要定义一个注解类

@Retention(RetentionPolicy.CLASS)
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
public @interface DebugTrace {
}

在需要插入代码的地方加入这个注解,例如在MainActivity中加入:

public class MainActivity extends AppCompatActivity{final String TAG = MainActivity.class.getSimpleName();@Overrideprotedcted void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);logTest();}@DebugTracepublic void logTest(){Log.e(TAG,”log test");}
}

最后创建切入代码

@Pointcut(“execution(@com.kun.aspectjtest.aspect.DebugTrace * *..*.*(..))”)
public void DebugTraceMethod(){}@Before(“DebugTraceMethod()”)
public void beforeDebugTraceMethod(JoinPoint joinPoint) throws Throwable{String key = joinPoint.getSignature().toString();Log.e(TAG, “beforeDebugTraceMethod:”+key);
}

Call

在AspectJ的切入点表达式中,我们前面都是使用的execution,实际上还有一种类型—call,那么这两种语法有什么区别呢?对call来说:

Call (Before)
Pointcut{Pointcut Method
}
Call (After)

对Execution来说:

Pointcut{execution (Before)Pointcut Methodexecution (After)
}

Withincode

这个语法通常来进行一些切入点条件的过滤,作更加精确的切入控制,如下:

public class MainActivity extends AppCompatActivity{final String TAG = MainActivity.class.getSimpleName();@Orverideprotected void onCreate(Bundle savedInstanceState){super.onCreate(saveInstanceState);setContentView(R.layout.activity_main);aspectJ1();aspectJ2();aspectJ3();}public void aspectJTest(){Log.e(TAG,”execute aspectJTest");}public void aspectJ1(){aspectJTest();}public void aspectJ2(){aspectJTest();}public void aspectJ3(){aspectJTest();}
}

aspectJ1(),aspectJ2(),aspectJ3()都调用了aspectJTest方法,但只想在aspectJ2调用aspectJTest时插入代码,这个时候就需要使用到Pointcut和withcode组合的方式,来精确定位切入点。

@Pointcut(“(call(* *..aspectJTest()))&&withincode(* *..aspectJ2())”)
public void invokeAspectJTestInAspectJ2(){
}@Before(“invokeAspectJTestInAspectJ2()”)
public void beforeInvokeaspectJTestInAspectJ2(JoinPoint joinPoint) throws Throwable{Log.e(TAG,”method:”+getMethodName(joinPoint).getName());
}private MethodSignature getMethodName(JoinPoint joinPoint){if(joinPoint == null) return null;return (MethodSignature) joinPoint.getSignature();
}

execution 语法

execution()是最常用的切点函数,其语法如下所示:
例如下面这段语法:
@Around(“execution(* *..MainActivity+.on*(..))")
整个表达式可以分为五个部分:

  1. execution()是表达式主体
  2. 第一个*号代表返回类型,*号代表所有的类型。
  3. 包名 表示需要拦截的包名,这里使用*.代表匹配所有的包名。
  4. 第二个*号表示类名,后面跟.MainActivity是指具体的类名叫MainActivity。
  5. *(..) 最后这个星号表示方法名,+.代表具体的函数名,*号通配符,包括括弧号里面表示方法的参数,两个dot代表任意参数。

遇到的错误

  1. 以下错误可以使用gradle2.2.3解决,由于目前还不适配gradle3.0导致的
Error:Execution failed for task ':app:transformClassesWithDexBuilderForDebug'.
> Unexpected scopes found in folder '/Users/ram/WorkSpace/AndroidWorkSpace/MyDemo/app/build/intermediates/transforms/AspectTransform/debug'. Required: PROJECT, SUB_PROJECTS, EXTERNAL_LIBRARIES. Found: EXTERNAL_LIBRARIES, PROJECT, PROJECT_LOCAL_DEPS, SUB_PROJECTS, SUB_PROJECTS_LOCAL_DEPS

转载于:https://www.cnblogs.com/cavalier-/p/8888459.html

在Android项目中使用AspectJ相关推荐

  1. android aspectj 参数,在Android项目中使用AspectJ

    什么是AOP AOP是 Aspect Oriented Programming 的缩写,即面向切面编程,和日常遇到的面向对象OOP编程不同的是,OOP是将功能模块化对象化,AOP是针对同一类的问题统一 ...

  2. android使用webview上传文件,Android项目中如何在webview页面中上传文件

    Android项目中如何在webview页面中上传文件 发布时间:2020-11-26 15:56:27 来源:亿速云 阅读:68 作者:Leah 本篇文章为大家展示了Android项目中如何在web ...

  3. Android项目中创建编译期的注解

    ==注解 生命周期为RetentionPolicy.RUNTIME,可在运行时通过反射获取. 生命周期为RetentionPolicy.CLASS, 编译期处理的注解,可以使用APT(Annotati ...

  4. Android项目中出现的Plugin with id ‘kotlin-android‘ not found解决方法

    Android项目中出现的Plugin with id 'kotlin-android' not found解决方法 参考文章: (1)Android项目中出现的Plugin with id 'kot ...

  5. flutter打开android界面,在已有Android项目中使用Flutter

    实现效果,在已存在的android项目中接入flutter,即android调用开启flutter页面(使用android打开flutter的指定页面),flutter调用原生android方法 步骤 ...

  6. XamarinSQLite教程在Xamarin.Android项目中提取数据库文件

    XamarinSQLite教程在Xamarin.Android项目中提取数据库文件 由于不能直接打开该文件,开发者需要先将数据库文件从Android系统中提取出来.操作步骤如下. (5)选择MyDoc ...

  7. XamarinSQLite教程在Xamarin.Android项目中定位数据库文件

    XamarinSQLite教程在Xamarin.Android项目中定位数据库文件 实际开发中,经常需要验证数据库操作的正确性.这个时候,需要打开数据库文件,进行确认.下面是如何找到MyDocumen ...

  8. XamarinSQLite教程在Xamarin.Android项目中使用数据库

    XamarinSQLite教程在Xamarin.Android项目中使用数据库 在Xamarin.Android项目中使用预设数据库的具体操作步骤如下: (1)创建一个Xamarin.Android项 ...

  9. android项目中导入opencv库,将第二个JNI库包含到我的Android项目(OpenCV)后...

    我试图将OpenCV添加到我现有的Android项目中,但是在合并它们时遇到了以下错误: 12-08 16:15:21.951 22052-22052/ai.inbi.face_recognition ...

最新文章

  1. 在text html模版中写js,Rails3使用text/html内容类型而不是text/javascript呈现js.erb模板...
  2. 如何用两个开关控制同一盏灯
  3. 大数据下union all的视图分页解决方案
  4. MFC日志(2011.4.9)
  5. SQL Server应用程序中的高级SQL注入
  6. [转载] 机器学习 - 如何使用 Java 调取 Python、R 的训练模型?
  7. Ubuntu 11.10为何值得我们期待?
  8. oracle 模拟阻塞,Oracle 阻塞(blocking blocked)介绍和实例演示
  9. 【MFC开发(6)】复选框按钮控件Check Box
  10. Sql面试50题 详解 持续更新
  11. 英语演讲和英语课件ppt模板
  12. CoreIDRAW出现“尝试重新启动计算机和应用程序...”问题解决方案
  13. 武汉星起航跨境:跨境电商新蓝海,南非跨境电商市场迸发活力
  14. 计算机字体安装按钮灰色,解决方案:在win10系统上将字体的安装按钮显示为灰色的详细步骤...
  15. latex中 号什么含义?
  16. 微软近日更新网页版Skype增通知版面和关键词搜寻
  17. 日本处方药【治疗肠癌】
  18. 计算机专业平均年龄,平均年龄27.07岁 去年23万人才“涌入”深圳
  19. UVM实战windows下运行
  20. DX9光照效果-------VB6编程学习DX9游戏编程DirectX9编程2D小游戏源码冷风引擎CoolWind2D游戏引擎(12)

热门文章

  1. css3 transform实现水平和垂直居中
  2. git中文件的三种状态
  3. [ACM训练] ACM中巧用文件的输入输出来改写acm程序的输入输出 + ACM中八大输入输出格式...
  4. ERP开发中应用字符串解析实现界面翻译智能化
  5. java corepoolsize_理解ThreadPoolExecutor线程池的corePoolSize、maximumPoolSize和poolSize
  6. springboot springcloud区别_SpringBoot回顾、Spring Cloud初学
  7. tcpdump 抓二层包_可能是我见过的最简单易懂且实用的 TCPDump 和 Wireshark 抓包及分析教程!( 强烈建议收藏 )...
  8. AUTOSAR从入门到精通-AUTOSAR PPT介绍
  9. 树莓派退出python的代码_Python实现树莓派WiFi断线自动重连的实例代码
  10. C语言输出最后一个空格去掉,新人提问:如何将输出时每行最后一个空格删除...