AOP、ASPECT、Spring AOP、JDK动态代理、CGLib动态代理
1 AOP介绍
1.1 基本定义
AOP(Aspect Oriented Programming)
称为面向切面编程,它是一种编程思想,是对OOP(Object Oriented Programming)
的补充,可以进一步提高编程效率,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等,Struts2
的拦截器设计就是基于AOP
的思想,是个比较经典的例子
1.2 解释
要理解切面编程,就需要先理解什么是切面。用刀把一个西瓜分成两瓣,切开的切口就是切面;炒菜,锅与炉子共同来完成炒菜,锅与炉子就是切面。web
层级设计中,web
层->网关层->服务层->数据层,每一层之间也是一个切面。编程中,对象与对象之间,方法与方法之间,模块与模块之间都是一个个切面
举例说明,一般在编写web服务接口时,进入某个接口后会检验当前是否需要登录,有部分接口需要登录才能访问,而有部分接口不需要登录也可以访问
按照正常的逻辑而言,我们会这样做:
但是这种方法存在一个问题,即代码的重复度高,每个接口都要编写相当的检测代码,不利于维护和扩展。因此,为了提高代码的复用性,考虑将所有公共代码抽取成一个公共方法,每个接口调用该方法进行检测,这里有点切面的味道了
第二版的方法相比第一版的重复代码减少了,系统的扩展性和代码的复用性也提高了,但是还是存在问题,即每个接口都要调用该方法,也会存在相同代码。因此,便提出了“切面”的概念,将该方法注入到接口调用的某个地方(切点),因此无需编写调用方法的代码,每次在方法运行前会自动在切点处调用该方法,进一步提升了系统的扩展性,并降低了代码之间的耦合度
这样接口只需要关心具体的业务,而不需要关注其他非该接口关注的逻辑或处理。红框处,就是面向切面编程
1.3 AOP中的相关概念
-
切面(Aspect)
切面是一个横切关注点的模块化,一个切面能够包含同一个类型的不同增强方法,比如说事务处理和日志处理可以理解为两个切面。切面由切入点和通知组成,它既包含了横切逻辑的定义,也包括了切入点的定义。
Spring AOP
就是负责实施切面的框架,它将切面所定义的横切逻辑织入到切面所指定的连接点中@Component @Aspect //可以简单地认为, 使用 @Aspect 注解的类就是切面 public class LogAspect { }
-
目标对象(Target)
**目标对象指将要被增强的对象,即包含主业务逻辑的类对象。**或者说是被一个或者多个切面所通知的对象,即就是被通知的对象。这些对象中已经只剩下干干净净的核心业务逻辑代码,所有的共有功能等待AOP容器的切入
-
连接点(JoinPoint)
程序执行过程中明确的点,如方法的调用或特定的异常被抛出。连接点由两个信息确定:
(1)方法(表示程序执行点,即在哪个目标方法)
(2)相对点(表示方位,即目标方法的什么位置,比如调用前,后等)
简单来说,连接点就是被拦截到的程序执行点,因为Spring只支持方法类型的连接点,所以在Spring中连接点就是被拦截到的方法
@Before("pointcut()") public void log(JoinPoint joinPoint) { //这个JoinPoint参数就是连接点 }
-
切入点(PointCut)
切入点是对连接点进行拦截的条件定义。切入点表达式如何和连接点匹配是AOP的核心,Spring缺省使用AspectJ切入点语法。 一般认为,所有的方法都可以认为是连接点,但是我们并不希望在所有的方法上都添加通知,而切入点的作用就是提供一组规则(使用 AspectJ pointcut expression language 来描述) 来匹配连接点,给满足规则的连接点添加通知
@Pointcut(value = "@annotation(authorityVerify)") public void pointcut(AuthorityVerify authorityVerify) { //该切入点的匹配规则是所有加了@AuthorityVerify注解的函数,并且通过authorityVerify还可以获得注解中的相关信息 } @Pointcut("execution(* com.remcarpediem.test.aop.service..*(..))") public void pointcut<