内容简介:AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。数据埋点,日志记录,性能统计,安全控制,事务处理,异常处理等等将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些
AspectJ是一个面向切面的框架,它扩展了 Java 语言。AspectJ定义了AOP语法,它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
主要功能
数据埋点,日志记录,性能统计,安全控制,事务处理,异常处理等等
目的(为什么要用AspectJ)
将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
原理
AspectJ在代码的编译期间扫描目标程序,根据切点(PointCut)匹配,将开发者编写的Aspect程序编织(Weave)到目标程序的.class文件中,对目标程序作了重构(重构单位是JoinPoint),目的就是建立目标程序与Aspect程序的连接(获得执行的对象、方法、参数等上下文信息),从而达到AOP的目的。
Gradle 配置示例
要引入AspectJ到Android工程中,最重要的就是两个包:
//在buildscript中添加该编织器,gradle构建时就会对class文件进行编织 //在buildscript中添加该 工具 包,在构建工程的时候执行一些任务:打日志等
classpath 'org.aspectj:aspectjtools:1.8.11' classpath 'org.aspectj:aspectjweaver:1.8.9' 复制代码
//在dependencies中添加该依赖,提供@AspectJ语法
compile 'org.aspectj:aspectjrt:1.8.9' 复制代码
//在app中的gradle
import org.aspectj.bridge.IMessage import org.aspectj.bridge.MessageHandler import org.aspectj.tools.ajc.Main 复制代码
//打印gradle日志
android.applicationVariants.all { variant ->
JavaCompile javaCompile = variant.javaCompile
javaCompile.doLast {
String[] args = ["-showWeaveInfo",
"-1.5",
"-inpath", javaCompile.destinationDir.toString(),
"-aspectpath", javaCompile.classpath.asPath,
"-d", javaCompile.destinationDir.toString(),
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", project.android.bootClasspath.join(
File.pathSeparator)]
MessageHandler handler = new MessageHandler(true);
new Main().run(args, handler)
def log = project.logger
for (IMessage message : handler.getMessages(null, true)) {
switch (message.getKind()) {
case IMessage.ABORT:
case IMessage.ERROR:
case IMessage.FAIL:
log.error message.message, message.thrown
break;
case IMessage.WARNING:
case IMessage.INFO:
log.info message.message, message.thrown
break;
case IMessage.DEBUG:
log.debug message.message, message.thrown
break;
}
}
}
}
复制代码
AspectJ官网配置
fernandocejas.com/2014/08/03/…
语法
切面——Aspect
在AOP中切面是标记执行被切点标记方法的逻辑处理。就是切点要处理的具体逻辑在切面这个模块。
连接点——JoinPoint
它是切面插入执行应用程序的地方,他能被方法调用,也能新增方法,JoinPoint是一个执行链,每一个JoinPoint是一个单独的闭包,在执行的时候将上下文环境赋予闭包执行方法体逻辑。
AspectJ的joinpoint有如下:
method call 函数调用 method execution 函数执行 constructor call 构造函数调用 constructor execution 构造函数执行 field get 获取某个变量 field set 设置某个变量 pre-initialization Object在构造函数中做得一些工作。 initialization Object在构造函数中做得工作 static initialization 类初始化 handler 异常处理,比如try catch(xxx)中,对应catch内的执行 advice execution 里面有3个标记(Around Before After) 复制代码
切点——PointCut
切点的声明决定需要切割的JoinPoint的集合,Pointcut可以控制你把哪些advice应用于JoinPoint上去,通常通过正则表达式来进行匹配应用,决定了那个jointpoint会获得通知。分为call、execution、target、this、within等关键字等。
within(TypePattem) TypePattern标示package或者类。TypePatter可以使用通配符 withincode(ConstructorSignaturelMethodSignature) 表示某个构造函数或其他函数执行过程中涉及到的JPoint cflow(pointcuts) cflow是call flow的意思,cflow的条件是一个pointcut cflowbelow(pointcuts) 表示调用pointcuts函数时所包含的JPoint,不包括pointcuts这个JPoint本身 this(Type) JPoint的this对象是Type类型 target(Type) JPoint的target对象是Type类型 args(TypeSignature) 用来对JPoint的参数进行条件搜索的 复制代码
匹配规则
(1)类型匹配语法 类型匹配的通配符: *:匹配任何数量字符; ..:匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数。 +:匹配指定类型的子类型;仅能作为后缀放在类型模式后边。 AspectJ使用 且(&&)、或(||)、非(!)来组合切入点表达式。
(2)匹配模式 call(<注解?> <修饰符?> <返回值类型> <类型声明?>.<方法名>(参数列表) <异常列表>?)
精确匹配
//表示匹配 com.sunmi.MainActivity类中所有被@Describe注解的public void方法。
@Pointcut("call(@Describe public void com.sunmi.MainActivity.init(Context))")
public void pointCut(){}
单一模糊匹配
//表示匹配 com.sunmi.MainActivity类中所有被@Describe注解的public void方法。
@Pointcut("call(@Describe public void com.sunmi.MainActivity.*(..)) ")
public void pointCut(){}
//表示匹配调用Toast及其子类调用的show方法,不论返回类型以及参数列表,并且该子类在以com.sunmi开头的包名内
@Pointcut("call(* android.widget.Toast+.show(..)) && (within(com.sunmi..*))")
public void toastShow() {
}
组合模糊匹配
//表示匹配任意Activity或者其子类的onStart方法执行,不论返回类型以及参数列表,且该类在com.sunmi包名内
@Pointcut("execution(* *..Activity+.onStart(..))&& within(com.sunmi.*)")
public void onStart(){}
复制代码
示例代码
有注解
声明一个注解 AopPoint
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AopPoint {
String value();
int type() default 0;
}
复制代码
在Activity 中,定义了2个按钮的点击事件,在方法上都标记注解,指定了value 和type。
@AopPoint(value = "首页点击",type = 1)
public void doFunc1(View view) {
SystemClock.sleep(1000);
}
@AopPoint("分类点击")
public void doFunc2(View view) {
SystemClock.sleep(1000);
}
复制代码
编写一个切面类
@Aspect
public class AopAspect {
@Pointcut("execution(@com.example.davis.aspectdemo.AopPoint * *(..))")
public void aopCut(){
}
@Around("aopCut()")
public Object dealMethod(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature= (MethodSignature) joinPoint.getSignature();
AopPoint aopPoint=signature.getMethod().getAnnotation(AopPoint.class);
String value=aopPoint.value();
int type=aopPoint.type();
TimeTool timeTool=new TimeTool();
timeTool.start();
Object result=joinPoint.proceed();
timeTool.stop();
Log.e("aopCut",value+" 执行时间="+timeTool.getTotalTimeMillis() +" type类型是"+type);
return result;
}
}
复制代码
结果
无注解
1、这个是扫描Activity 中onCreate方法的调用
@Aspect
public class FuncTAspect {
@Before("execution(* android.app.Activity.onCreate(..))")
public void onActivityMethodBefore(JoinPoint joinPoint) throws Throwable {
String key = joinPoint.getSignature().toString();
Log.e("FuncTAspect", "onActivityMethodBefore: " + key+"\n"+joinPoint.getThis());
}
}
复制代码
结果只能扫描到onCreate方法
如果把onCreate改成通配符* android.app.Activity.onCreate(..) 改成android.app.Activity.*(..)
结果
2、捕获catch异常
@Aspect
public class ExceptionHandleAspect {
private static final String TAG = "ExceptionHandleAspect";
/**
* 截获空指针异常
*
* @param e
*/
@Pointcut("handler(java.lang.Exception)&&args(e)")
public void handle(Exception e) {
}
/**
* 在catch代码执行之前做一些处理
*
* @param joinPoint
* @param e 异常参数
*/
@Before(value = "handle(e)", argNames = "e")
public void handleBefore(JoinPoint joinPoint, Exception e) {
Log.e(TAG, joinPoint.getSignature().toLongString() + " handleBefore() :" + e.toString());
}
}
复制代码
在方法里制造一个Null指针
public void doFunc1(View view) {
try {
AppItem appItem=null;
appItem.number=2;
}catch (Exception e){}
}
复制代码
结果
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 应用编程基础课第三讲:Go编程基础
- 应用编程基础课第三讲:Go编程基础
- 应用编程基础课第四讲:Go编程实践
- 15个流行编程语言及其应用
- Go Web 编程--应用 ORM
- Go Web 编程--应用ORM
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
JavaScript & jQuery
David Sawyer McFarland / O Reilly / 2011-10-28 / USD 39.99
You don't need programming experience to add interactive and visual effects to your web pages with JavaScript. This Missing Manual shows you how the jQuery library makes JavaScript programming fun, ea......一起来看看 《JavaScript & jQuery》 这本书的介绍吧!