AOP
AOP是 Aspect Oriented Programming 的缩写,即“面向切面编程”,通过使用AOP可以在编译期间对代码进行动态管理,达到统一维护的目的。AOP其实是OOP编程思想的一种延续,利用AOP,我们可以对业务逻辑的各个模块进行隔离,降低模块间耦合度,提高程序的可重用性,进而提高开发效率。利用AOP,我们还可以在无侵入的状态下在宿主中插入一些代码逻辑,从而实现诸如日志埋点、性能监控、动态权限控制等。
AOP相关术语
- Advice : 增强
- JoinPoint : 连接点
- PointCut : 切点
- Aspect : 切面
- Weaving : 织入
- Target : 目标对象
Advice
增强,又叫“通知”,是指织入到目标类连接点上的一段层序代码
JoinPoint
连接点,即程序执行的某个特定位置,如类开始初始化前、类初始化后、类中的某个方法调用前后、方法抛出异常后等。一个类或一段程序代码拥有一些具有边界性质的特定点就是连接点,如果一个类有两个方法,那么这两个方法都是连接点,即连接点是程序中客观存在的事物。
PointCut
切点,也叫“切入点”,每个程序类都拥有多个连接点,AOP通过“切点”来定位特定的连接点。连接点相当于数据库中的记录,而切点相当于查询条件,一个切点可以对应多个连接点。
Aspect
切面,由切点和增强组成,包括连接点和横切逻辑的定义
Weaving
织入,织入是将增强添加到目标类具体连接点上的过程,根据不同的实现技术,AOP有三种不同的织入方式:
- 编译器织入,需要使用特殊的Java编译器
- 类装载期织入,需要使用特殊的类装载器
- 动态代理织入,在运行期为目标类添加增强生成子类的方式
Target
目标对象,增强逻辑的织入目标类
了解完以上相关术语后大家可能还不太明白是怎么一回事,我们用白话来总结下:
- 我们通过定义一个表达式(PointCat)来告诉程序,我们需要对哪个地方进行额外的操作,通过这个表达式(PointCat),我们得到了那些需要通知的方法(JoinPoint)
- 我们还需要告诉程序,这些方法(JoinPoint)需要做怎样的增强(Advice)
- 什么时候进行额外的操作(执行前/执行后/执行前后/返回之前),额外操作具体要做什么,我们把以上两步定义到一个地方(Aspect)
- 进行额外的操作所涉及到被修改的对象称为目标对象(Target)
- 完成上面所有的操作动作,总成为织入(Weaving)
AspectJ
上面我们已经了解了AOP的概念,AspectJ实际上是对AOP编程思想的实现,可以和java配合起来使用。
AspectJ最核心的模块就是它提供的ajc编译器,它将AspectJ的代码在编译器插入到目标程序当中,ajc会构建目标程序与AspectJ代码的联系,在编译期将AspectJ代码插入到被切出的PointCut中,从而达到AOP的目的。
如果想对AspectJ有更多的了解,可以看其官网:http://www.eclipse.org/aspectj/
AspectJ相关的注解类
@Aspect
用来描述一个切面类,编译期会被AspectJ的ajc编译器识别
@Aspect
public class ClickBehaviorAspect {
}
@PointCut
用来定义切点,标记方法
@Pointcut("execution(@com.jokerwan.aoploginsample.annotation.ClickBehavior * *(..))")
public void methodPointcut() {
}
上面标记了com.jokerwan.aoploginsample.annotation.ClickBehavior类的所有方法,“* *(…)”表示所有方法
@Before
前置增强,在某连接点之前执行的增强
@Before("execution(* android.view.View.OnClickListener.onClick(android.view.View))")
public void onViewClickAOP(final JoinPoint joinPoint){
View view = (View) joinPoint.getArgs()[0];
TrackApi.getInstance().trackViewOnClick(view);
}
@After
后置增强,在某连接点之后执行增强
@After("execution(* android.view.View.OnClickListener.onClick(android.view.View))")
public void onViewClickAOP(final JoinPoint joinPoint){
View view = (View) joinPoi