AOP 即 Aspect Oriented Programming,面向切面编程。
AOP 允许程序员模块化横向业务逻辑,或定义核心部分的功能,例如日志管理和事务管理。
1 AOP 术语
- 通知(Advice)
通知
表示在方法执行前后需要执行的动作,是切面
真正要做的工作。通知负责定义切面
的what
和when
。
- 连接点(JointPoint)
连接点
表示在应用中可以插入切面
,执行通知
的地点。
- 切点(Pointcut)
切点
定义了where
。切点
指定一个或者多个连接点
,而通知
通过切点接入。
- 切面(Aspect)
切面
=通知
+切点
。定义what
、when
和where
。是 AOP 的核心,将多个类的通用行为封装为可重用的模块。
- 引入(Introduction)
引入
允许向现有类添加新方法或属性。类似于设计模式中的装饰者模式——在不改变现有类的基础上为之增加属性和方法。
- 织入(Weaving)
织入
是把切面
应用到目标对象并创建新的代理对象的过程。切面
在指定的连接点
被织入到目标对象中。- 在目标对象的生命周期里有多个点可以进行织入:编译期(AspectJ)、类加载期(LTW)、运行期(Spring AOP)
- 目标对象
- 被一个或者多个
切面
所通知
的对象。它通常是一个代理对象。也被称做被通知(advised)对象。
- 被一个或者多个
- 代理
代理
是将通知
应用到目标对象后创建的对象。从客户端的角度看,代理对象和目标对象是一样的。
- 自动代理
- BeanNameAutoProxyCreator:bean名称自动代理创建器
- DefaultAdvisorAutoProxyCreator:默认通知者自动代理创建器
- Metadata autoproxying:元数据自动代理
- Concern(核心逻辑)
- 表示在应用程序中一个模块的行为。Concern 可以定义为我们想要实现的功能。
- Cross-cutting concern(横向的通用逻辑)
- 指的是整个应用程序都会用到的功能,它影响整个应用程序。例如,日志管理(Logging)、安全管理(Security)以及数据交互
2 Spring 的 AOP 支持
Spring 对 AOP 有以下四种支持:
- 基于代理的 Spring AOP
- Pure-POJO aspects
- 基于 @AspectJ 注解的 aspects
- 注入 AspectJ aspects(所有版本的 Spring 都支持)
前三种属于 Spring AOP 框架,基于动态代理机制构建,仅支持函数级别的拦截。如果需要实现更复杂的 AOP 功能,则应使用 AspectJ 框架。
在 Spring AOP 框架中,通过在 beans 的外围包含一个代理类来将切面织入到这些 beans。调用者跟代理类直接联系,代理类拦截函数调用,然后执行切面逻辑之后再调用真正的目标对象的方法。
虽然 Spring AOP 能够满足许多应用的切面需求, 但是与 AspectJ 相比, Spring AOP 是一个功能比较弱的 AOP 解决方案。 AspectJ 提供了 Spring AOP 所不能支持的许多类型的切点。
AOP 的源码中用到了两种动态代理来实现拦截切入功能:
- jdk 动态代理
- jdk 动态代理是由 java 内部的反射机制来实现的,反射机制在生成类的过程中比较高效
- 如果加入容器的目标对象有实现接口,用 JDK 代理;
- Cglib 动态代理
- cglib 动态代理底层则是借助 asm 来实现的,asm 在生成类之后的相关执行过程中比较高效
- 如果目标对象没有实现接口,用 Cglib 代理
3 AspectJ
AspectJ 注解生效
通过类级别的 @EnableAspectJAutoProxy 注解开启自动代理机制
@Configuration
@EnableAspectJAutoProxy //开启AspectJ的自动代理机制
@ComponentScan
public class ConcertConfig {
}