




下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】如何在Android项目中使用AspectJ方法
如何在Android项目中使用AspectJ方法?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Android是一种基于Linux内核的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由美国Google公司和开放手机联盟领导及开发。什么是AOPAOP是AspectOrientedProgramming的缩写,即面向切面编程,和平常遇到的面向对象OOP编程不一样的是,OOP是将功能模块化对象化,AOP是针对同一类的问题统一化处理。例如做日志埋点,性能监控,动态权限控制等。AspectJAspectJ实际上是对AOP编程的实践,目前还有很多的AOP实现,如ASMDex,但笔者选用的是AspectJ。在Android项目中使用AspectJ如果使用原生AspectJ在项目中配置会非常麻烦,在GitHub上有个开源的SDKgradle_plugin_android_aspectjx基于gradle配置即可。接入说明请自行查看开源项目中的接入配置过程AspectJ之JoinPoints介绍JoinPoints在AspectJ中是关键的概念。JoinPoints可以看做是程序运行时的一个执行点,比如:一个函数的调用可以看做是个JoinPoints,相当于代码切入点。但在AspectJ中,只有下面几种执行点是认为是JoinPoints:Pointcuts介绍一个程序会有多个JoinPoints,即使同一个函数,也还分为call和execution类型的JoinPoints,但并不是所有的JoinPoints都是我们关心的,Pointcuts就是提供一种使得开发者能够值选择所需的JoinPoints的方法。AdviceAdvice就是我们插入的代码可以以何种方式插入,有Before还有After、Around。下面看个例子:@Before(“execution(*
android.app.Activity.on**(..)))”)
public
void
onActivityMethodBefore(JoinPoint
joinPoint)
throws
Throwable{
}这里会分成好几个部分,我们依次来看:@Before:Advice,也就是具体的插入点execution:处理JoinPoint的类型,例如call、execution(*android.app.Activity.on**(..)):这个是最重要的表达式,第一个*表示返回值,*表示返回值为任意类型,后面这个就是典型的包名路径,其中可以包含*来进行通配,几个*没有区别。同时这里可以通过&&、||、!来进行条件组合。()代表这个方法的参数,你可以指定类型,例如android.os.Bundle,或者(..)这样来代表任意类型、任意个数的参数。publicvoidonActivityMehodBefore:实际切入的代码。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);
proceedingJoinPceed();
Log.d(TAG,”onActivityMethodAroundSecond:”+key);
}以上代码中,proceedingJoinPceed()代表执行原始的方法,在这之前、之后,都可以进行各种逻辑处理。自定义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();
@Override
protedcted
void
onCreate(Bundle
savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
logTest();
}
@DebugTrace
public
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
Method
execution
(After)
}Withincode这个语法通常来进行一些切入点条件的过滤,作更加精确的切入控制,如下:public
class
MainActivity
extends
AppCompatActivity{
final
String
TAG
=
MainActivity.class.getSimpleName();
@Orveride
protected
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:Executionfailedfortask':app:transformClassesWithDexBuilderForDebug'.>Unexpectedscopesfoundinfolder'/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_DEPSError:Executionfailedfortask':app:transformClassesWithDexBuilderForDebug'.>Unexpectedscopesfoundinfolde
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 个体租山林合同范本
- 企业退货合同范本
- 厂房消防环保合同范本
- 整容手术合同范本
- 车险担保合同范本
- 2025年河北廊坊开发区公开选调工作人员40名备考练习题库及答案解析
- 空间病毒消毒合同范本
- 打混凝土合同范本
- 2025年合肥市朝霞小学教师招聘备考练习试题及答案解析
- 2025年实验诊断学实验室检查常见异常结果解释试题答案及解析
- (2025秋新版)部编版八年级上册道德与法治全册教案
- 八年级心理健康体验式教学计划
- 二手房资金监管协议书
- 消防监控考试题初级及答案
- 2025年太阳能海水淡化项目经济效益评估报告
- 2025年湖南湘西自治州州直事业单位招聘考试笔试试卷附答案
- 《小学开学第一课》课件
- 2025-2031年中国有源相控阵雷达行业市场发展形势及投资潜力研判报告
- 大货车货运安全知识培训课件
- 消防车辆事故课件
- 2026届四川省宜宾市普通高中高一化学第一学期期末统考试题含解析
评论
0/150
提交评论