AOP简介
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
1、aop中的术语语
Joinpoint(连接点) | 所谓连接点是指那些被拦截到的点 |
Pointcut(切入点) | 所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义 |
Advice(通知/增强) | 所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知 |
Introduction(引介) | 引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类 动态地添加一些方法或 Field |
Target(目标对象) | 代理的目标对象 |
Weaving(织入) | 是指把增强应用到目标对象来创建新的代理对象的过程. AspectJ 采用编译期织入和类装在期织入 |
Proxy(代理) | 一个类被 AOP 织入增强后,就产生一个结果代理类 |
Aspect(切面) | 是切入点和通知(引介)的结合 |
2、advice分类
Before | 前置通知, 在目标执行之前执行通知 |
After | 后置通知, 目标执行后执行通知 |
Around | 环绕通知, 在目标执行中执行通知, 控制目标执行时机 |
AfterReturning | 后置返回通知, 目标返回时执行通知 |
AfterThrowing | 异常通知, 目标抛出异常时执行通知 |
3、切入点指示符
execution | 用于匹配方法执行的连接点 |
within | 用于匹配指定类型内的方法执行 |
this | 用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配 |
target | 用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配 |
args | 用于匹配当前执行的方法传入的参数为指定类型的执行方法 |
@within | 用于匹配所以持有指定注解类型内的方法 |
@target | 用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解 |
@args | 用于匹配当前执行的方法传入的参数持有指定注解的执行 |
@annotation | 用于匹配当前执行方法持有指定注解的方法 |
aspectj使用
此项目是给予aspect1.9.4版本开发 minSdkVersion必须大于24
1、app.gradle添加依赖
dependencies {
implementation 'org.aspectj:aspectjrt:1.9.4'
}
2、project.gradle添加依赖
dependencies {
classpath 'com.android.tools.build:gradle:3.3.2'
classpath 'org.aspectj:aspectjtools:1.9.4'
}
3、app.gradle添加任务,添加在最外层
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
final def log = project.logger
final def variants = project.android.applicationVariants
//在构建工程时,执行编辑
variants.all { variant ->
if (!variant.buildType.isDebuggable()) {
log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")
return;
}
JavaCompile javaCompile = variant.javaCompile
javaCompile.doLast {
String[] args = ["-showWeaveInfo",
"-1.9",
"-inpath", javaCompile.destinationDir.toString(),
"-aspectpath", javaCompile.classpath.asPath,
"-d", javaCompile.destinationDir.toString(),
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]
log.debug "ajc args: " + Arrays.toString(args)
MessageHandler handler = new MessageHandler(true);
new Main().run(args, handler);
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:
log.warn message.message, message.thrown
break;
case IMessage.INFO:
log.info message.message, message.thrown
break;
case IMessage.DEBUG:
log.debug message.message, message.thrown
break;
}
}
}
}
4、新建interface BehaviorTrance.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BehaviorTrance {
String value();
}
5、新建 BehaviorTraceAspect.java
需要将execution中的com.example.aoptest.aspectj.annotation.BehaviorTrance换成你自己的包名
@Aspect
public class BehaviorTraceAspect {
@Pointcut("execution(@com.example.aoptest.aspectj.annotation.BehaviorTrance * *(..))")
public void methodAnnottatedWithBehaviorTrace() {
}
@Before("methodAnnottatedWithBehaviorTrace()")
// @After("methodAnnottatedWithBehaviorTrace()")
public void before(JoinPoint point) {
MethodSignature methodSignature = (MethodSignature) point.getSignature();
String className = methodSignature.getDeclaringTypeName();
String methodName = methodSignature.getName();
String value = methodSignature.getMethod().getAnnotation(BehaviorTrance.class).value();
Log.d("zkq", String.format("%s功能:%s类的%s方法执行了",value, className, methodName));
Log.d("zkq", "2222222222222222");
}
}
6、在mainActivity.java中的任意方法就可以使用了,我这里是一个点击事件
@BehaviorTrance("点击方法")
public void onAspectj(View view) {
Log.d("zkq","111111");
}
总结
在BehaviorTraceAspect中如果我们用到的是Around就需要使用ProceedingJoinPoint并且抛出Throwable,并且在目标执行中执行的先后顺序是由Object result = joinPoint.proceed()来决定的
@Around("methodAnnottatedWithBehaviorTrace()")
private Object methodBehaviorTrace(ProceedingJoinPoint joinPoint) throws Throwable{
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String className = methodSignature.getDeclaringTypeName();
String methodName = methodSignature.getName();
String value = methodSignature.getMethod().getAnnotation(BehaviorTrance.class).value();
Log.d("zkq", String.format("%s功能:%s类的%s方法执行了",value, className, methodName));
Object result = joinPoint.proceed();
return result;
}
demo下载地址: demo下载