android studio 中怎么写aspectj代码,Android Studio 使用 AspectJ 实践AOP

Android Studio 官方暂时不支持aspectJ,不过这里用的一款gradle插件 aspectjx

配置在project的build.gradle里配置插件dependencies {

classpath 'com.android.tools.build:gradle:2.1.3'

//if i update the gradle plugin version above to 2.2.0,it will runs out with a problerm

classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:1.0.7'

}在主module中添加 apply plugin:'android-aspectjx',在android闭包中添加aspectjx {

//指定只对含有关键字'DataBindingDemo/aspectjlibrary'的库进行织入扫描,忽略其他库,提升编译效率

includeJarFilter 'DataBindingDemo/aspectjlibrary'

//排除对universal-image-loader'库的织入扫描

// excludeJarFilter 'universal-image-loader'

}在使用了aspectj 的module中添加一下依赖:compile 'org.aspectj:aspectjrt:1.8.9'

应用

aspect 主要用于AOP编程,应用在日志,监控,性能检查方面,并可以做到无侵入。

首先是3个概念:

JoinPoint :表示程序运行过程中的一些执行点,包括函数调用,函数内部执行等。。。

PointCut : 用于定位到指定的JoinPoint

Advice : 要织入到指定位置的代码片段

新建一个Module,专门用于编写Aspectj代码,将该Module申明成android library,主Module中添加该依赖库。

新建一个类 ActivityAspect,在类名上添加注解@Aspect。声明一个PointCut:public static final String MainMethod = "* com.github.huangyouqiang.aspectjlibrary.databindingdemo.MainActivity.*(..)"

@Pointcut("execution(MainMethod)")

public void mainmethod(){}

其中MainMethod表示匹配MainActivity中的所有方法。具体语法如下:Method Signature:

语法: @注解 访问权限 返回值的类型 包名.函数名(参数)

@注解 和 访问权限public/private/protect,以及static/final)属于可选项。如果不设置它们,则默认都会选择。以访问权限 为例,如果没有设置访问权限作为条件,那么public,private,protect及static、final的函数都会进行搜索。

返回值类型就是普通的函数的返回值类型。如果不限定类型的话,就用*通配符表示

Ž 包名.函数名用于查找匹配的函数。可以使用通配符,包括和..以及+号。其中号用于匹配除.号之外的任意字符,而..则表示任 意子package,+号表示子类。

比如:

java.*.Date:可以表示java.sql.Date,也可以表示java.util.Date

Test*:可以表示TestBase,也可以表示TestDervied

java..*:表示java任意子类

java..*Model+:表示Java任意package中名字以Model结尾的子类,比如TabelModel,TreeModel等

最后来看函数的参数。参数匹配比较简单,主要是参数类型,比如:

(int, char):表示参数只有两个,并且第一个参数类型是int,第二个参数类型是char

(String, ..):表示至少有一个参数。并且第一个参数类型是String,后面参数类型不限。在参数匹配中,

..代表任意参数个数和类型

(Object …):表示不定个数的参数,且类型都是Object,这里的…不是通配符,而是Java中代表不定参数的意思

Constructor signature:

和Method Signature类似,只不过构造函数没有返回值,而且函数名必须叫new。比如:

public *..TestDerived.new(..):

Œ public:选择public访问权限

*..代表任意包名

Ž TestDerived.new:代表TestDerived的构造函数

(..):代表参数个数和类型都是任意

Field Signature:

@注解 访问权限 类型 类名.成员变量名

Œ 其中,@注解和访问权限是可选的

类型:成员变量类型,*代表任意类型

Ž 类名.成员变量名:成员变量名可以是*,代表任意成员变量

比如,

set(int test..TestBase.base):表示设置TestBase.base变量时的JPoint

Type Signature:

staticinitialization(test..TestBase):表示TestBase类的static block

handler(NullPointerException):表示catch到NullPointerException的JPoint.

@Pointcut()定义了一个PointCut,注解了一个方法public void mainmethod(){},此处这个方法不需要具体实现,此方法变代表了这个PointCut,下面会用到。execution表示为该匹配为该函数类型的JoinPoint的内部执行。

结合上述的解释,可以得出该PointCut可定位到MainActivity中任一方法的内部执行的类型的JoinPoint。

接下来,编写真正要织入的代码:@Around("method()")

public void onPreMethod(ProceedingJoinPoint joinPoint)throws Throwable{

Log.i(TAG,joinPoint.getSignature().getName()+" -->start");

long startNanos = System.nanoTime();

Object result = joinPoint.proceed();

long stopNanos = System.nanoTime();

long lengthMillis = TimeUnit.NANOSECONDS.toMillis(stopNanos - startNanos);

Log.i(TAG,joinPoint.getSignature().getName()+"-->end execute time total : "+lengthMillis+"ms")

}

这个advice使用了@Around("method()")注解,其中的method()便是上文定义的PointCut,Around,顾名思义,即包围,在这个函数内部执行的前后,该注解修饰的方法就是具体执行的代码,参数为固定的ProceedingJoinPoint,在该函数内部又这么一条Object result = joinPoint.proceed(); 这条表示调用原函数自己的是实现,返回的result也是原函数的返回值,我们就可以在这个函数的前后添加需要的功能了,比如日志记录和耗时计算。如果不调用这一句,则原函数便不会执行了。另外,通过这个JoinPoint参数,可以获取到该方法的签名对象以及该方法的调用者对象,再通过反射,可以实现更多的功能,[email protected],[email protected],@After,[email protected],所以不展开,具体用法一样,只是参数类型变为JoinPoint。

至此,就完成了一个简单的完整的AspectJ应用,可以满足基本的需求了。

上文所述是基于方法的对JoinPoint的代码织入,还有基于构造方法的,基于类的成员变量的。

以下是一个基于成员变量的例子,对该变量的赋值的joinPoint织入:

首先在MainActivit中声明一个变量int i ;,在onCreate()中赋值i = 3;,接下来编写aspectj代码,@Pointcut("set(int com.github.huangyouqiang.aspectjlibrary.databindingdemo.MainActivity.i) && args(i)")

public void seti(int i){}

@Before("seti(i)")

public void beforeI(JoinPoint joinPoint,int i){

FieldSignature signature = (FieldSignature) joinPoint.getSignature();

System.out.println(joinPoint.getStaticPart().getSourceLocation());

System.out.println(signature.getName()+ " = "+i);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值