如何实现Spring AOP以及Spring AOP的实现原理

简介: 如何实现Spring AOP以及Spring AOP的实现原理

AOP:面向切面编程,它和OOP(面向对象编程)类似。

AOP组成:

1、切面:定义AOP是针对那个统一的功能的,这个功能就叫做一个切面,比如用户登录功能或方法的统计日志,他们就各种是一个切面。切面是有切点加通知组成的。

2、连接点:所有可能触发AOP(拦截方法的点)就称之为连接点。

3、切点:定义AOP拦截的规则的。

4、通知:规定AOP执行的时机和执行的方法。(前置通知、后置通知、抛出异常之后通知、返回数据之后通知、环绕通知)

Spring AOP的实现步骤:

1.先项目中添加Spring AOP框架支持

2.定义切面

3.定义切点

4.实现通知

步骤1:引入框架支持

步骤2:定义切面

步骤3.定义切点,设置拦截规则(这里Aspect语法下面会介绍)

步骤4.实现通知方法(在什么时机执行什么方法)(这里只列了一种通知方法,下面几种通知都回介绍)


接着上面所说的,这里介绍一下Aspect J的语法:

Aspect J的语法

示例:

execution(<修饰符><返回类型><包.类.⽅法(参数)><异常>) (修饰符和异常可以省略)

修饰符一般省略:

Public 公共方法

* 任意

返回值不能省略:

Void 没有返回值

String 返回值为字符串

* 任意

包:

com.gyf.crm 固定包

com.gyf.crm.*.service crm包下面子包任意

com.gyf.crm.. crm包下面的所有子包(含自己)

com.gyf.crm.*.service.. crm包下面任意子包,固定目录service,service目录任意包

类:

UserServiceDemo 指定类

*Demo 以Demo结尾的类

User* 以User开头的类

* 任意

方法名:

addUser 固定方法

add* 以add开头的方法

*Do 以Do结尾的方法

* 任意

参数:

() 无参

(int) 一个整型

(int,int) 两个参数

(..) 任意参数

示例

execution(* com.cad.demo.User.*(..)) :匹配 User 类⾥的所有⽅法。

execution(* com.cad.demo.User+.*(..)) :匹配该类的⼦类包括该类的所有⽅法。

execution(* com.cad.*.*(..)) :匹配 com.cad 包下的所有类的所有⽅法。

execution(* com.cad..*.*(..)) :匹配 com.cad 包下、⼦孙包下所有类的所有⽅法。

execution(* addUser(String, int)) :匹配 addUser ⽅法,且第⼀个参数类型是 String,第⼆个

参数类型是 int。

Aspect J语法总结:

关于Aspect语法中的通配符:

1、* 表示匹配任意的内容,用在返回值,包名、类名、方法名都可以使用。

2、.. 匹配任意字符,可以使用在方法参数上,如果用在类上需要配合*一起使用。

3、+ 表示匹配指定类及其它底下的所有子类,比如 com.Car+表示匹配 Car及其所有的子类。

如何定义相关通知:

通知定义的是被拦截的⽅法具体要执⾏的业务,⽐如⽤户登录权限验证⽅法就是具体要执⾏的业务。Spring AOP 中,可以在⽅法上使⽤以下注解,会设置⽅法为通知⽅法,在满⾜条件后会通知本⽅法进⾏调⽤:

前置通知使⽤@Before:通知⽅法会在⽬标⽅法调⽤之前执⾏。

后置通知使⽤@After:通知⽅法会在⽬标⽅法返回或者抛出异常后调⽤。

返回之后通知使⽤@AfterReturning:通知⽅法会在⽬标⽅法返回后调⽤。

抛异常后通知使⽤@AfterThrowing:通知⽅法会在⽬标⽅法抛出异常后调⽤。

环绕通知使⽤@Around:通知包裹了被通知的⽅法,在被通知的⽅法通知之前和调⽤之后执⾏⾃定义的⾏为。

具体实现如下:


在没有异常抛出的情况下,我们可以看看他们各自执行的顺序:

在我们手动设置异常后,再看他们的执行顺序:


可以看到,即使有异常抛出了,执行了AfterThrowing方法,但是还是会继续执行完毕。

我们也可以使用环绕通知实现统计每个方法的执行时间,具体实现如下:


注意:我们可以根据joinPoint.getSignature().getDeclaringTypeName()+"."+ joinPoint.getSignature().getName() 得到类的类型和名称,在前面我们new了stopWatch对象,调用了start和stop方法,后面我们在调用stopWatch.getTotalTimeMillis()就可以得到耗费时间了。

Spring AOP的实现原理

Spring AOP ⽀持 JDK Proxy 和 CGLIB ⽅式实现动态代理。默认情况下,实现了接⼝的类,使⽤ AOP 会基于 JDK ⽣成代理类,没有实现接⼝的类,会基于 CGLIB ⽣成代理类。

Spring AOP动态代理实现:

在 class 代码运⾏期,动态的织⼊字节码。主要基于两种方式:

1、JDK Proxy (JDK动态代理,前提是需要有实现了接口的类,通过反射获得目标对象)

2、CGLIB Proxy :默认情况下Spring AOP都会采用CGLIB来实现动态代理。

CGLIB来实现动态代理的原理:通过继承代理对象来实现动态代理的(子类拥有父类的所有功能)。缺点:不能代理最终类(也就是被final修饰的类)。

JDK 动态代理和 CGLIB 动态代理都是常见的动态代理实现技术,但它们有以下区别:

JDK 动态代理基于接口,要求目标对象实现接口;CGLIB 动态代理基于类,可以代理没有实现接口的目标对象。

JDK 动态代理使用 java.lang.reflect.Proxy 和 java.lang.reflect.InvocationHandler 来生成代理对象;CGLIB 动态代理使用 CGLIB 库来生成代理对象。

JDK 动态代理生成的代理对象是目标对象的接口实现;CGLIB 动态代理生成的代理对象是目标对象的子类。

JDK 动态代理性能相对较高,生成代理对象速度较快;CGLIB 动态代理性能相对较低,生成代理对象速度较慢。

JDK 动态代理无法代理 final 类和 final 方法;CGLIB 动态代理可以代理任意类的方法。

总结:

AOP 是对某⽅⾯能⼒的统⼀实现,它是⼀种实现思想,Spring AOP 是对 AOP 的具体实现,Spring AOP 可通过 @Aspect(注解)的⽅式来实现 AOP 的功能。Spring AOP 是通过动态代理的⽅式,在运⾏期将 AOP 代码织⼊到程序中的,它的实现⽅式有两种: JDK Proxy 和 CGLIB。


相关文章
|
7月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
715 0
|
11月前
|
监控 安全 Java
Spring AOP实现原理
本内容主要介绍了Spring AOP的核心概念、实现机制及代理生成流程。涵盖切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)等关键概念,解析了JDK动态代理与CGLIB代理的原理及对比,并深入探讨了通知执行链路和责任链模式的应用。同时,详细分析了AspectJ注解驱动的AOP解析过程,包括切面识别、切点表达式匹配及通知适配为Advice的机制,帮助理解Spring AOP的工作原理与实现细节。
1519 13
|
6月前
|
XML Java 数据格式
《深入理解Spring》:AOP面向切面编程深度解析
Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
|
XML Java 开发者
Spring Boot中的AOP实现
Spring AOP(面向切面编程)允许开发者在不修改原有业务逻辑的情况下增强功能,基于代理模式拦截和增强方法调用。Spring Boot通过集成Spring AOP和AspectJ简化了AOP的使用,只需添加依赖并定义切面类。关键概念包括切面、通知和切点。切面类使用`@Aspect`和`@Component`注解标注,通知定义切面行为,切点定义应用位置。Spring Boot自动检测并创建代理对象,支持JDK动态代理和CGLIB代理。通过源码分析可深入了解其实现细节,优化应用功能。
676 6
|
8月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
8月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
1017 0
|
XML Java 测试技术
Spring AOP—通知类型 和 切入点表达式 万字详解(通俗易懂)
Spring 第五节 AOP——切入点表达式 万字详解!
1081 25
|
XML 安全 Java
Spring AOP—深入动态代理 万字详解(通俗易懂)
Spring 第四节 AOP——动态代理 万字详解!
586 24
|
Java API 微服务
微服务——SpringBoot使用归纳——Spring Boot中的切面AOP处理——Spring Boot 中的 AOP 处理
本文详细讲解了Spring Boot中的AOP(面向切面编程)处理方法。首先介绍如何引入AOP依赖,通过添加`spring-boot-starter-aop`实现。接着阐述了如何定义和实现AOP切面,包括常用注解如`@Aspect`、`@Pointcut`、`@Before`、`@After`、`@AfterReturning`和`@AfterThrowing`的使用场景与示例代码。通过这些注解,可以分别在方法执行前、后、返回时或抛出异常时插入自定义逻辑,从而实现功能增强或日志记录等操作。最后总结了AOP在实际项目中的重要作用,并提供了课程源码下载链接供进一步学习。
1649 0
下一篇
开通oss服务