Spring的AOP是什么?

AOP是Aspect-Oriented Programming的缩写,主要目的是减少代码重复,降低模块间耦合。AOP通过代理模式实现,Spring AOP和AspectJ是两种常见实现。Spring AOP使用动态代理,而AspectJ采用编译时增强。切点定义拦截方法,通知定义增强逻辑。Spring通知类型包括前置、后置、环绕、返回后和异常后通知。理解这些概念有助于提升系统可维护性。

1、什么是AOP?

AOP(Aspect-Oriented Programming:面向切面编程):是指将那些与业务无关,却被多个业务模块所共同调用逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,提升系统的可维护性。

2、AOP的实现有哪两种方式?

AOP实现的关键在于代理模式,主要有两种实现方式,分别是AspectJ AOP和Spring AOP。

3、Spring AOP 和 AspectJ AOP 有什么区别?

AspectJ AOP使用的是静态代理方式,也称为编译时增强,AOP框架会在编译阶段生成AOP代理类,并将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象。

Spring AOP使用的是动态代理方式,也就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用 Cglib 生成一个被代理对象的子类来作为代理。

另外,Spring AOP 也已经集成了AspectJ 。

AspectJ 相比于 Spring AOP 功能更加强大,性能更好,但是 Spring AOP 相对来说使用更简单。

4、Spring AOP里面的几个名词的概念

(1)连接点(Join point):指程序运行过程中所执行的方法。在Spring AOP中,一个连接点总代表一个方法的执行。 

(2)切面(Aspect):被抽取出来的公共模块,可以用来横切多个对象。Aspect切面可以看成 Pointcut切点 和 Advice通知 的结合,一个切面可以由多个切点和通知组成。在Spring AOP中,切面可以在类上使用 @AspectJ 注解来实现。

(3)切点(Pointcut):切点用于定义 要对哪些Join point进行拦截。

切点分为execution方式和annotation方式。execution方式可以用路径表达式指定对哪些方法拦截,比如指定拦截add*、search*。annotation方式可以指定被哪些注解修饰的代码进行拦截。

(4)通知(Advice):指要在连接点(Join Point)上执行的动作,即增强的逻辑,比如权限校验和、日志记录等。通知有各种类型,包括Around、Before、After、After returning、After throwing。

(5)目标对象(Target):包含连接点的对象,也称作被通知(Advice)的对象。 由于Spring AOP是通过动态代理实现的,所以这个对象永远是一个代理对象。

(6)织入(Weaving):通过动态代理,在目标对象(Target)的方法(即连接点Join point)中执行增强逻辑(Advice)的过程。

整个流程串联起来就是,通过切点(Pointcut)的表达式或者注解的定义,找到相应的连接点(Joinpoint)即目标对象中(Target)的某个方法,将相应的通知(Advice)织入(Weaving)到这些连接点(Joinpoint)处。

切点和通知组成了切面,连接点其实就是连接的切点和通知。

5、Spring通知(Advice)有哪些类型?

(1)前置通知(Before Advice):在连接点(Join point)之前执行的通知。

(2)后置通知(After Advice):当连接点退出的时候执行的通知(不论是正常返回还是异常退出)。 

(3)环绕通知(Around Advice):包围一个连接点的通知,这是最强大的一种通知类型。 环绕通知可以在方法调用前后完成自定义的行为。它也可以选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。

(4)返回后通知(AfterReturning Advice):在连接点正常完成后执行的通知(如果连接点抛出异常,则不执行)

(5)抛出异常后通知(AfterThrowing advice):在方法抛出异常退出时执行的通知

所有通知的执行顺序如下:

同一个Aspect,不同advice的执行顺序:

(1)没有异常情况下的执行顺序:

     around before advice
→ before advice 
→ target method 执行
→ around after advice
→ after advice
→ afterReturning

(2)有异常情况下的执行顺序:

     around before advice
→ before advice
→ target method 执行
→ around after advice
→ after advice
→ afterThrowing
→ java.lang.RuntimeException: 异常发生

 

 

 

### Spring AOP 的概念 Spring AOP(Aspect-Oriented Programming,面向切面编程)是 Spring 框架中用于解决横切关注点(cross-cutting concerns)的一种编程范式。常见的横切关注点包括日志记录、事务管理、安全性检查等,这些功能通常会重复出现在多个业务模块中。通过 AOP,可以将这些通用逻辑从业务代码中解耦出来,提升代码的复用性和可维护性。 AOP 核心概念包括: - **切面(Aspect)**:封装横切关注点的模块,例如一个日志切面。 - **连接点(Join Point)**:程序执行过程中的特定点,如方法调用或异常抛出。 - **通知(Advice)**:在连接点上执行的具体操作,如前置通知、后置通知等。 - **切入点(Pointcut)**:定义哪些连接点需要被拦截并应用通知。 - **代理对象(Proxy)**:由 Spring 生成的目标对象的代理,用于执行切面逻辑[^2]。 --- ### Spring AOP 的原理 Spring AOP 是基于动态代理机制实现的。其核心思想是在运行时为目标类生成代理对象,并在代理对象的方法调用前后插入切面逻辑。Spring AOP 主要支持两种代理方式: 1. **JDK 动态代理**:适用于目标类实现了接口的情况。通过 `java.lang.reflect.Proxy` 类动态创建代理对象。 2. **CGLIB 代理**:适用于目标类没有实现接口的情况。通过继承目标类的方式生成子类作为代理对象[^5]。 当使用 Spring AOP 时,框架会在运行时根据配置自动选择合适的代理方式,并将切面逻辑织入到目标方法中。这种“织入”过程对开发者是透明的,无需修改原有业务代码即可完成功能增强。 --- ### Spring AOP 的作用 Spring AOP 的主要作用在于解耦和增强系统的横切关注点,具体表现为以下几点: - **统一处理通用逻辑**:例如日志记录、性能监控、事务控制等功能可以通过切面集中管理,避免代码冗余。 - **提高代码可维护性**:将业务逻辑与非功能性需求分离,使代码结构更清晰,便于后期维护。 - **增强系统扩展性**:新增切面功能无需修改已有代码,符合开闭原则。 - **简化开发流程**:开发者只需关注核心业务逻辑,而无需关心日志、安全等辅助功能的实现细节[^4]。 --- ### 示例代码:Spring Boot 中使用 AOP 以下是一个简单的 Spring Boot AOP 示例,展示了如何记录方法执行时间: #### 添加依赖 ```xml <!-- 在 pom.xml 中添加 AOP 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> ``` #### 定义切面类 ```java import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; @Aspect @Component public class LoggingAspect { @Around("execution(* com.example.service.*.*(..))") public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { long start = System.currentTimeMillis(); Object result = joinPoint.proceed(); // 执行目标方法 long executionTime = System.currentTimeMillis() - start; System.out.println(joinPoint.getSignature() + " executed in " + executionTime + "ms"); return result; } } ``` 上述代码定义了一个切面类 `LoggingAspect`,其中 `logExecutionTime` 方法用于记录目标方法的执行时间,并通过 `@Around` 注解指定其为环绕通知。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值