# Spring AOP
# 简要回答
- AOP是面向切面的编程,允许开发者在不改动业务代码的情况下横向切入添加新的功能,比如日志。切面包含很多类型和对象,AOP以切面为单位对它们进行模块化管理,可以减少系统重复代码,降低模块间的耦合度。
- AOP使用Java的动态代理机制,能够在运行时动态的创建代理对象,开发者在不修改源码的情况下增强方法功能,动态代理包含基于JDK的动态代理和基于CGLIB的动态代理。
# 详细回答
# AOP概念
- AOP(Aspect Oriented Programming),面向切面的编程,是面对对象编程的完善。**面向对象编程引入封装,继承和多态的概念建立对象层次,但是无法定义横向关系。**以日志功能为例,日志代码会横向散布在所有对象层次中,对应对象的核心功能毫无关系,这些代码就是横切,在面对对象设计中,会产生大量代码的重复,不利于各个模块的重用。
- AOP技术可以将日志、安全性、异常处理这些影响了多个类的公共行为封装到一个可重用模块中,命名为切面(Aspect)。切面将这些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,有利于未来的可操作性和可维护性。
- 使用"横切"技术, AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核 心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。 AOP 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
# AOP重要术语
- 横切关注点: 对哪些方法进行拦截,拦截后怎么处理。
- 切面( aspect):类是对物体特征的抽象,切面就是对横切关注点的抽象,切面对横切关注点进行封装。
- 连接点( joinpoint ):程序执行中被拦截到的点,因为 Spring 只支持方法类型的连接点,所以在 Spring中连接点指的就是被拦截到的方法调用或者执行时的特定时间,实际上连接点还可以是字段或者构造器。
- 切入点( pointcut ):对连接点进行拦截的定义,即筛选规则。
- 通知( advice ):指的是拦截到连接点之后要执行的代码,通知分为前置(Before)、后置(After)、返回(AfterReturning)、异常(AfterThrowing)、环绕通知(Around)五类。前四种通知在目标方法前后执行,环绕通知可以控制目标方法执行过程。
| 通知类型 | 执行时机 |
|---|---|
| 前置通知(Before) | 目标方法执行之前执行 |
| 后置通知(After) | 目标方法执行之后执行(无论是否抛出异常) |
| 返回通知(AfterReturning) | 目标方法正常执行完毕并返回结果后执行 |
| 异常通知(AfterThrowing) | 目标方法执行过程中抛出异常时执行 |
| 环绕通知(Around) | 包裹目标方法,在目标方法执行前后均可执行逻辑,还能控制目标方法是否执行、修改返回值等,功能最强 |
- 目标对象:代理的目标对象。
- 代理对象:代理对象会执行切面的通知逻辑,再调用目标对象的原始方法。
- 织入( weave ):将切面应用到目标对象最后生成代理对象的过程。
- 引入( introduction)在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段。
# Spring中的AOP
Spring中的AOP代理由 Spring 的 IOC 容器负责生成、管理,其依赖关系也由IOC容器负责管理。因此,AOP代理可以直接使用容器中的其它 bean 实例作为目标,这种关系可由 IOC 容器的依赖注入提供。
spring 创建代理的规则为:
- 默认使用 JDK动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了
- 当需要代理的类不是代理接口的时候, Spring 会切换为使用CGLIB代理,也可强制使用CGLIB
AOP编程实现步骤:
- 定义普通业务组件。
- 定义切入点,一个切入点可能横切多个业务组件
- 定义增强处理,增强处理就是在 AOP框架为普通业务组件织入的处理动作
- 一旦定义了合适的切入点和增强处理, AOP框架将自动生成 AOP代理,即: 代理对象的方法=增强处理+被代理对象的方法。
# 动态代理的方式
基于JDK的动态代理:只提供接口的代理,不支持类的代理。核心接口是InvocationHandler和Proxy类。
- InvocationHandler通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起。Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。
基于CGLIB的动态代理:代理类没有实现InvocationHandler接口时,SpringAOP使用CGLIB动态代理目标类。
- CGLIB是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,覆盖其中特定方法并添加增强代码以实现AOP。
- CGLIB通过继承方式做动态代理,如果某个类被标记为final则无法使用CGLIB。
# 知识图解
- AOP不同类型通知时机

# 知识扩展
- 面试官可能追问?
- 动态代理和静态代理有什么区别?
- 代理是一种常用的设计模式,为其他对象提供一个代理以控制对某个对象的访问,解耦两个类的关系。
- 静态代理是由程序员创建或由特定工具创建,在代码编译时就确定了被代理的类。
- 动态代理是在代码运行期间,运用反射机制动态创建生成的,动态代理的是一个接口下的多个实现类。
- AOP有哪些注解?
- @ Aspect:定义切面,标注在切面类上。
- @ Pointcut:定义切点,标注在方法上,用于指定连接点。
- @ Before:在方法被调用之前执行通知。
- @ After:在方法被调用后之后执行通知。
- @ Around:任意的在方法调用前后执行。
- @ AfterReturning:在方法执行返回结果后执行通知。
- @ AfterThrowing:在方法抛出异常后执行通知。
- @ Advice:通用的通知类型,替代@ Before、@ After。
- 动态代理和静态代理有什么区别?
评论
验证登录状态...