什么是AOP
AOP是面向切面编程,将公共逻辑(如:日志、事务管理等)封装成切面,跟业务代码分开,做到了解耦的效果。
AOP有哪些实现方式?
动态代理和静态代理
静态代理:在编译时就将代码写入字节码,称为编译时增强
动态代理:在代码运行的时候在内存中创建一个代理类,不会修改字节码,
静态代理:AspectJ
动态代理:Spring
Spring AOP 的实现原理
通过动态代理实现。
如果对Spring的某个bean做了切面的话,那么Spring实际创建的是这个bean的代理对象,而不是直接实例化原始的bean。这个代理对象会拦截对该bean的调用,并在适当的时候调用自定义的通知逻辑。
Spring的AOP实现主要依赖两种实现形式:
- JDK动态代理
- CGLIB动态代理
JDK动态代理和CGLIB动态代理有什么区别
JDK动态代理
如果目标对象至少实现了一种接口,那么默认会采用该代理方式。
JDK动态代理只能对实现了接口的对象代理,它通过反射机制生成目标对象的代理对象, 并拦截对接口方法的调用,从而实现目标方法的增强处理。
CGLIB代理
如果目标对象没有实现任何接口,那么将会采用该代理方式。
CGLIB动态代理通过生成目标类的子类(动态子类),并重写非final非private方法以插入通知代码。
思考:如果一个类没有实现接口并且被final修饰,是否无法被代理?
是的。此时可以考虑移除final修饰符或改为AspectJ静态代理,因为该代理方式可以处理final类和方法,因为他是写入字节码当中的。
Spring通知有哪些类型?
切面的工作被称为通知。通俗来说就是要通过Spring AOP框架来触发的代码段。
Spring AOP 支持多种类型的通知(Advice),这些通知允许你在不同的执行点插入横切逻辑。以下是 Spring AOP 中的主要通知类型:
-
@Before通知 (前置通知):- 在连接点(通常是方法执行)之前运行,但不会影响连接点的执行流程。无论目标方法是否抛出异常或正常返回,
@Before通知都会执行。 - 示例:用于日志记录、权限检查等。
- 在连接点(通常是方法执行)之前运行,但不会影响连接点的执行流程。无论目标方法是否抛出异常或正常返回,
-
@AfterReturning通知 (返回通知):- 在连接点成功完成后运行,即目标方法正常返回后执行。你可以访问并处理目标方法的返回值。
- 示例:用于结果缓存、性能监控等。
-
@AfterThrowing通知 (异常通知):- 当连接点抛出异常时运行。你可以捕获特定类型的异常,并执行相应的逻辑。
- 示例:用于异常日志记录、事务回滚等。
-
@After(finally) 通知 (后置通知):- 无论连接点是正常完成还是抛出异常,
@After通知都会执行。它类似于 Java 的finally块。 - 示例:用于资源清理、关闭数据库连接等。
- 无论连接点是正常完成还是抛出异常,
-
@Around通知 (环绕通知):- 这是最强大的通知类型,它可以在连接点前后都执行代码,并且可以控制是否继续执行连接点。
@Around通知还可以访问和修改参数及返回值。 - 示例:用于实现复杂的环绕逻辑,如事务管理、自定义方法拦截等。
- 这是最强大的通知类型,它可以在连接点前后都执行代码,并且可以控制是否继续执行连接点。
Spring AOP 相关术语总结
Spring AOP(面向切面编程)涉及多个术语,理解这些术语对于掌握 Spring AOP 的使用和原理非常重要。以下是与 Spring AOP 相关的一些关键术语:
-
Aspect(切面):
- 切面是模块化的特殊类,它包含了切入点(Pointcut)和通知(Advice)。一个切面定义了横切关注点(cross-cutting concern),如事务管理、日志记录等。
-
Join Point(连接点):
- 连接点是指程序执行过程中的一个点,例如方法调用、异常抛出或字段访问。在 Spring AOP 中,连接点总是表示为方法执行。Spring AOP 仅支持方法级别的连接点。
-
Pointcut(切入点):
- 切入点是一个表达式或模式,用于匹配特定的连接点。它决定了哪些连接点将被通知(Advice)所影响。可以通过正则表达式或其他方式来定义切入点。
-
Advice(通知/增强处理):
- 通知是在特定的连接点上执行的动作。根据通知执行的时间点,可以分为以下几种类型:
@Before:在方法执行之前运行。@AfterReturning:在方法成功完成后运行。@AfterThrowing:在方法抛出异常后运行。@After(finally):无论方法是否完成,都会运行。@Around:包围连接点,在方法调用前后都运行,并可以控制是否继续执行连接点。
- 通知是在特定的连接点上执行的动作。根据通知执行的时间点,可以分为以下几种类型:
-
Introduction(引入):
- 引入允许向现有的对象添加新的接口和属性。这使得目标对象可以在不修改其代码的情况下实现新的功能。
-
Target Object(目标对象):
- 目标对象是被一个或多个切面所通知的对象。它也是原始的业务逻辑对象,通常是由 Spring 容器管理的 bean。
-
AOP Proxy(AOP 代理):
- AOP 代理是由 AOP 框架创建的对象,用来实现代理功能。有两种类型的代理:JDK 动态代理和 CGLIB 代理。代理对象会拦截对目标对象方法的调用,并在适当的时候应用通知逻辑。
-
Weaving(织入):
- 织入是将切面与目标对象组合的过程。这个过程可以在编译时、类加载时或运行时进行。Spring AOP 使用的是运行时代理的方式进行织入。