1.概念
什么是AOP? Aspect Oriented Programming的缩写。意为:面向切面编程。是oop的延续。通过预编译和动态代理来实现程序的功能,统一维护的一种技术。AOP可以对业务逻辑的各个部分进行分离,从而使业务逻辑之间的耦合度降低。提高程序的可重用性。
动态代理
预编译方式
如何理解切面,把需要的抽取的相同的功能业务抽取出来。
取款,查询,转账每一步不同的功能都有验证用户的需求,就可以把验证用户抽取出来做成切面。
动态代理模式
预编译模式--面向切面思想之集中式登录思想架构
采用预编译模式由java文件编译成class文件就不能采用javac,而是要用AspectJ来代替。
AspectJ需要注意的是as和gradle版本。
as3.0.1 gradle4.4-all,这个版本需要配置ndk r17.
as3.2.1 gradle4.6-all,
as3.4.0 gradle5.1.1-all,这个版本会有api过时的警告
集成AspectJ步骤:
1.在project gradle中加入AspectJ classpath
dependencies {
classpath'com.android.tools.build:gradle:3.2.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath'org.aspectj:aspectjtools:1.8.9'
classpath'org.aspectj:aspectjweaver:1.8.9'
}
2.在module gradle中主要有三部
1.buildscript {//编译时需要用AspectJ专门的编译器
repositories {
mavenCentral()
}
dependencies {
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath'org.aspectj:aspectjtools:1.8.9'
classpath'org.aspectj:aspectjweaver:1.8.9'
}
}
2.添加依赖
dependencies {
implementation fileTree(dir:'libs',include: ['*.jar'])
implementation'androidx.appcompat:appcompat:1.0.2'
testImplementation'junit:junit:4.12'
implementation'org.aspectj:aspectjrt:1.8.13'
}
3.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.8",
"-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;
}
}
}
}
自定义标签
//用户使用统计
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClickBehavior {
Stringvalue();
}
添加标签
@ClickBehavior("登录")
public void land(View view) {
Log.e(TAG, "验证成功,登陆成功");
}
定义一个切面类
@Aspect//定义一个切面类
public class ClickBehaviorAspect {
private static final StringTAG ="AOP_Login";
//找到需要处理的切入点 execution,以方法执行时作为切点,触发Aspect类
//**(..)可以处理ClickBehavior这个类所有的方法,该切入点一点错误都不能有,有一处拼写错误就不会实现
@Pointcut("execution(@com.dezerlin.aop_login.annotation.ClickBehavior * *(..))")
public void abc() {//方法名无所谓
}
//对切入点如何处理 通过advice通知来执行 Around表示在我们切入的代码前后都可以执行,after在切入点之后执行,before在切入点之前执行
@Around(" abc()")
public ObjectjointPotin(ProceedingJoinPoint joinPoint)throws Throwable {
//获取签名方法
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
//获取方法所属的类名
String className=methodSignature.getDeclaringType().getSimpleName();
//获取方法名
String methodName=methodSignature.getName();
//获取方法的注解值
String funName=methodSignature.getMethod().getAnnotation(ClickBehavior.class).value();
long begin=System.currentTimeMillis();
Log.e(TAG,"start");
Object result= joinPoint.proceed();
long duration=System.currentTimeMillis()-begin;
Log.e(TAG,"end");
Log.e(TAG,String.format("统计了:%s功能,在%s类中的%s方法,用时$d ms",funName,className,methodName,duration));
return result;
}
}
通过 Object result= joinPoint.proceed() return result执行了自定义标签中的代码,而切入点前后的代码也执行了