AOP和AspectJ
通过预编译方式或者运行期动态代理实现程序功能的统一维护的一种技术。
面向对象编程主要用于为同一对象层面的公用行为建模。弱点是不能将公共行为用在多个无关对象之间。而面向切片编程最大的优点就是将公共行为用在不同的对象模块上。
AspectJ是一种语言来支持aop的,但是他也提供了java的方式使用AspectJ。
- joinpoint
- pointcut
- advice
使用aop的步骤
1. 添加配置
在module下的build.gradle文件中添加:
buildscript{
repositories {
mavenCentral()
}
dependencies{
classpath 'org.aspectj:aspectjtools:1.8.9'
classpath 'org.aspectj:aspectjweaver:1.8.9'
}
}
... // 省略
dependencies {
...
implementation 'org.aspectj:aspectjrt:1.8.9'
}
... // 省略
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;
}
}
}
}
2. 创建切片类
@Aspect
public class TestAspect {
@Pointcut("execution(* com.dou.demo.aop_demo.MainActivity.test(..))")
public void pointcut(){}
@Around("pointcut()")
public void test(ProceedingJoinPoint point) throws Throwable{
System.out.println("@test start");
point.proceed();
System.out.println("@test end");
}
}
实践(对方法进行耗时计算/权限检查)
定义annotation
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface Hugo {
}
使用注解
@Hugo
private void time_consumer() {
for (int i = 0; i < 100; i++){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
定义切片
@Aspect
public class HugoAspect {
@Pointcut("execution(@com.dou.demo.aop_demo.Hugo * *(..))")
public void hugo(){}
@Around("hugo()")
public void timer(ProceedingJoinPoint point) throws Throwable{
System.out.println("@hugo start");
MethodSignature signature = (MethodSignature) point.getSignature();
long starttime = System.currentTimeMillis();
point.proceed();
long endtime = System.currentTimeMillis();
System.out.println(signature.getMethod().getName() + " 方法耗时: " + (endtime - starttime) + " ms");
System.out.println("@hugo end");
}
}
重新clean,run
其它一个实例见源码
网友评论