一、AOP介绍
1、AOP是什么?
AOP即为面向切面编程,和Java的OOP面向对象编程一样,都是一种编程思想,一些先行者已经为面向切面编程开发了一套语言来支持。
2、AOP的作用是什么?
通过预编译的形式和运行期动态代理,来改变原来的执行结果。
3、AOP的特点?
(1)使原执行逻辑和切面逻辑进行解耦
(2)对源代码侵入性低
(3)容易扩展辅助功能(比如Android的埋点,跳转前的网络检查,权限检查等等,都不属于面向对象的模块内的东西,但是又是各个模块通用的东西)
4、AspectJ的介绍
AspectJ是一种几乎和Java一样的编程语言,完全兼容Java。在Android中通过AspectJ实现AOP有两种形式,第一种是使用AspectJ这种语言。
第二种仍然使用Java语言,给Java语言打上一些标签,能让AspectJ的编译器识别即可。
在Android中使用AspectJ,说白点,就是在编译成点class的过程中,不再使用Java的编译器了,而是使用AspectJ的编译器。
这个编译器和Java的编译器没太多的区别,唯一是,它会根据@Aspect标签的类,找到切点和切面,再反推去找到被切点标记的注解,看哪些方法用到这些注解。
然后进行一个代码植入方案。本质上没有性能的问题。
二、在Android中的使用
1、定义一个注解
/**
* Target表示这个注解用在什么地方,当前是Method方法上。有类、构造函数、函数、属性等选项
* Retention表示注解保留多久
* 1、RUNTIME表示运行时,即编译后,注解仍然在,并且会随着class加载进入JVM
* 2、CLASS表示编译时,即编译后,注解仍然在,但是JVM加载class文件时会被抛弃掉
* 3、SOURCE表示源码,即编译后,注解就被编译器忽略了不存在了
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AddPoint {
String value();
}
2、定义一个切面和切点
/**
* @Aspect定义该类为切点切面处理类
*/
@Aspect
public class MyAspect {
/**
* @Pointcut表示切点 execution表示用在方法的执行内部
* call表示用在方法的调用处
* get/set一般用在变量、属性的使用上
* @com.zbh.aopdemo.AddPoint表示注解类所在的全地址,通过这个声明,就知道这个切点用在被这个地址注解的属性或者方法上了
* * * (..)表示被这个注解的所有方法,不管什么参数的,都要进行切点和切面处理
*/
@Pointcut("execution(@com.zbh.aopdemo.AddPoint * * (..))")
public void addPoint() {
}
/**
* @Before表示前置通知,切点前执行,方法执行前这里先执行
*/
@Before("addPoint()")
public void testBefore() {
Log.i("zhangbh", "Test Run Before");
}
/**
* @Around表示环绕通知,切点前后执行,相当于下面的代码会代替被注解标记的代码,其中point.proceed()就是把原来方法的代码挪到这一块
* return null的地方,那么切点的方法就不会被调用。比如下面这个执行,如果注解标记的@AddPoint("ABC"),那么该方法的方法体最终是不会被调用的
* @AddPoint("Test")这样,方法体就会被调用,可以理解为替换到这里面来
*/
@Around("addPoint()")
public Object dealPoint(ProceedingJoinPoint point) throws Throwable {
MethodSignature ms = (MethodSignature) point.getSignature();
AddPoint addPoint = ms.getMethod().getAnnotation(AddPoint.class);
String value = addPoint.value();
if ("Test".equals(value)) {
Log.i("zhangbh", "Test Run Start");
Object object = point.proceed();
Log.i("zhangbh", "Test Run End");
return object;
}
return null;
}
/**
* @After表示后置通知,切点后执行,方法执行后这里才执行
*/
@After("addPoint()")
public void testAfter() {
Log.i("zhangbh", "Test Run After");
}
}