【移动应用开发技术】如何在Android项目中使用AspectJ方法_第1页
【移动应用开发技术】如何在Android项目中使用AspectJ方法_第2页
【移动应用开发技术】如何在Android项目中使用AspectJ方法_第3页
【移动应用开发技术】如何在Android项目中使用AspectJ方法_第4页
【移动应用开发技术】如何在Android项目中使用AspectJ方法_第5页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】如何在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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论