秋招Day17 - Spring - AOP
什么是AOP?
AOP,也就是面向切面编程,简单点说,AOP 就是把一些业务逻辑中的相同代码抽取到一个独立的模块中,实现了业务逻辑和通用逻辑的分离。
AOP有哪些核心概念?
切面:横切关注面的抽象
连接点:所有潜在的拦截点,在Spring中是方法执行
切点:用来选择连接点的表达式
通知:拦截到连接点后要执行的代码,也叫增强
目标对象:代理的目标对象
引介:是一种特殊的增强(通知),可以动态地为类添加一些属性和方法。
织入:将切面应用到到目标类,创建出代理对象的过程
织入有哪几种方式?
- 编译时织入:切面在目标类编译时织入
- 类加载时织入:切面在目标类加载到JVM时被织入,目标类被被加载到JVM之前增强其字节码
- 运行期织入:切面在程序运行的某个时刻织入,这是Spring AOP采用的织入方式,AOP容器在织入时会为目标对象动态的创建一个代理对象
AOP有哪些环绕方式?
AOP 一般有 5 种环绕方式:
- 前置通知 (@Before)
- 返回通知 (@AfterReturning)
- 异常通知 (@AfterThrowing)
- 后置通知 (@After)
- 环绕通知 (@Around)
多个切面的情况下,可以通过 @Order
指定先后顺序。
Spring AOP发生在什么时候?
运行时通过动态代理,发生在BeanPostProcessor阶段,会创建出一个代理对象,并在代理对象中织入切面逻辑
简单总结一下AOP
AOP,也就是面向切面编程,是一种编程范式,旨在提高代码的模块化。比如说可以将日志记录、事务管理等分离出来,来提高代码的可重用性。
AOP 的核心概念包括切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)和织入(Weaving)等。
① 像日志打印、事务管理等都可以抽离为切面,可以声明在类的方法上。像 @Transactional
注解,就是一个典型的 AOP 应用,它就是通过 AOP 来实现事务管理的。我们只需要在方法上添加 @Transactional
注解,Spring 就会在方法执行前后添加事务管理的逻辑。
② Spring AOP 是基于代理的,它默认使用 JDK 动态代理和 CGLIB 代理来实现 AOP。
③ Spring AOP 的织入方式是运行时织入,而 AspectJ 支持编译时织入、类加载时织入。
AOP和OOP的关系?
互补
AOP是面向切面编程,可以抽象出公共逻辑为横切关注面,应用到目标类中
OOP是面向对象编程,主要用于业务逻辑,封装类的属性和行为
AOP的使用场景有哪些?
AOP 的使用场景有很多,比如说日志记录、事务管理、权限控制、性能监控等。
说说JDK动态代理和CGLIB
AOP是通过动态代理实现的,具体实现方式有两种:JDK动态和CGLIB代理
JDK动态代理是基于接口的,只能代理实现了接口的类。使用JDK动态代理时,Spring AOP会创建一个代理对象,该代理对象实现了目标对象所实现的接口,并在拦截到方法调用后转发到Handler,将方法执行前后插入横切逻辑。只依赖JDK自带的Proxy库
CGLIB是基于继承的代理,他会生成一个子类继承目标类,并在方法调用时转发到MethodInterceptor,然后将方法前后插入横切逻辑,需要额外依赖CGLIB库
选择CGLIB还是JDK动态代理?
- 如果目标对象没有实现任何接口,则只能使用 CGLIB 代理。如果目标对象实现了接口,通常首选 JDK 动态代理。
- 虽然 CGLIB 在代理类的生成过程中可能消耗更多资源,但在运行时具有较高的性能。对于性能敏感且代理对象创建频率不高的场景,可以考虑使用 CGLIB。
- JDK 动态代理是 Java 原生支持的,不需要额外引入库。而 CGLIB 需要将 CGLIB 库作为依赖加入项目中。
你会用JDK动态代理和CGLIB吗?
JDK动态代理
定义接口、实现接口、编写ProxyFactory(实现通过反射生成代理对象,用匿名内部类实现InvocationHandler的invoke方法,实现插入横切逻辑)、Client方调用ProxyFactory的getProxyInstance方法获取代理对象,通过代理对象调用目标对象方法
CGLIB代理
定义类、编写ProxyFactory(通过反射编写获取代理对象的方法,并继承MethodInterceptor重写intercept方法插入横切逻辑)、Client方调用ProxyFactory的getProxyInstance方法获取代理对象,通过代理对象调用目标对象方法
说说Spring AOP和AspectJ AOP的区别?
- Spring AOP只支持运行时织入,AspectJ AOP支持编译时织入、编译后织入和类加载时织入
- Spring AOP基于纯java,只能作用于Spring容器,AspectJ AOP支持单独使用
- Spring AOP性能不如AspectJ AOP,因为有运行时开销
- Spring AOP的连接点仅有方法执行这一种类型,AspectJ AOP的连接点类型包含方法执行字段
AOP和反射的区别?
反射:用于检查和操作目标类的方法和字段,动态调用方法或访问字段
动态代理:生成代理类来拦截方法调用,用于AOP的实现,动态代理使用反射来调用被代理的方法