需要引入额外的 CGLIB 库
发布时间:2025-06-24 18:50:27 作者:北方职教升学中心 阅读量:662
当目标类没有实现任何接口时,Spring 会使用 CGLIB 代理。环绕通知(Around Advice)
随着软件开发技术的不断进步,面向切面编程(AOP)作为一种重要的编程思想,已经在现代开发中占据了重要地位。Spring-Aop 模块补充
- 2.1、
2、AOP 前置概念
- 2.2、代理范围更广(包括普通类)。
- 局限性:目标类或方法不能声明为
final
,否则无法被继承和代理。
- 实现方式:创建一个实现了目标接口的代理类,并在方法调用前后插入增强逻辑。当目标对象实现了一个或多个接口时,Spring 会默认选择 JDK 动态代理。Spring-Aop 模块概述
- 1.2、希望本篇内容能为您打开通往 AOP 世界的大门,也期待您在实际工作中灵活运用所学,将代码的复杂度隐藏于优雅的设计之中,为团队和项目带来更大的价值。
- 局限性:目标类必须有接口。AOP 前置概念
首先,我们来确认一些 Spring 使用核心的 AOP 概念和术语。
Spring AOP 通过灵活的配置和强大的功能,可以轻松地将横切关注点从业务逻辑中分离出来,提高代码的可维护性和可扩展性。
@AspectpublicclassLoggingAspect{@Before("execution(* com.example.service.*.*(..))")publicvoidlogBefore(JoinPointjoinPoint){System.out.println("Before method: "+joinPoint.getSignature().getName());}}
2.3.2、
- 切面(Aspect):切面是 AOP 处理横切关注点的核心单元,它是对 横切逻辑的模块化封装,它包含切点和通知(切面 = 切点 + 通知)。但是,如果 Spring 使用自己的术语,那就更加令人困惑了。前置通知(Before Advice)
- 2.3.2、Spring AOP的实现
- 2.3、核心原理以及实战操作,帮助您在实际项目中更加得心应手地运用这一强大工具。需要引入额外的 CGLIB 库。
@EnableAspectJAutoProxy
:启用 AOP 的自动代理。Spring 配置类- 3.5、换句话说横切是问题,切面是解决方案。Spring AOP 模块本身不具备完整的 AOP 能力,需要依赖其他模块和工具(例如 AspectJ 或代理机制)来实现 AOP 功能。
@Before
:定义一个前置通知,在方法执行前触发。后置通知、依赖引入虽然 Spring AOP 是一个模块,但它需要依赖以下组件来完整实现 AOP 功能:
- Spring 核心模块:必须依赖 Spring 的核心模块(如
spring-context
和spring-beans
),用于 Bean 的创建和管理。@AfterThrowing(pointcut ="execution(* com.example.service.*.*(..))",throwing ="error")publicvoidlogAfterThrowing(JoinPointjoinPoint,Throwableerror){System.out.println("Exception in method: "+joinPoint.getSignature().getName());System.out.println("Exception: "+error);}
2.3.4、
- AspectJ(可选):Spring AOP 支持 AspectJ 注解,但必须引入
aspectjweaver
库。1.3、Spring 业务类
packagecom.lizhengi.example;importorg.springframework.stereotype.Component;/** * 用户业务类 */@Component// 标记为 Spring 管理的 BeanpublicclassUserService{publicvoidcreateUser(Stringname){System.out.println("User "+name +" created.");}publicvoiddeleteUser(Stringname){System.out.println("User "+name +" deleted.");}}
3.3、
2.2、后置通知(After Returning Advice)
- 2.3.3、Spring 切面类
packagecom.lizhengi.example;importorg.aspectj.lang.annotation.Aspect;importorg.aspectj.lang.annotation.Before;importorg.springframework.stereotype.Component;@Aspect// 声明这是一个切面@Component// 标记为 Spring 管理的 BeanpublicclassLoggingAspect{@Before("execution(* com.lizhengi.example.UserService.*(..))")// 定义切点publicvoidlogBefore(){System.out.println("Logging before method execution");}}
说明:
@Aspect
:标记为切面。切面的本质是一个包含横切逻辑的类,定义了横切逻辑执行的时机(通知)和适用的位置(切点)。前置通知(Before Advice)在目标方法执行之前执行。
CGLIB 代理:基于字节码生成技术,由
CGLIB
(Code Generation Library)库支持。其目的是让横切逻辑独立于业务代码,提高代码模块化程度。- 优点:无需引入额外的库(纯 JDK 实现)。
3.5、依赖引入
3.2、例如,为一个类增加性能监控的能力,不改变原始代码。Spring 业务类 3.3、 <dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.39</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.3.39</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.22.1</version></dependency></dependencies>
3.2、
@AfterReturning(pointcut ="execution(* com.example.service.*.*(..))",returning ="result")publicvoidlogAfterReturning(JoinPointjoinPoint,Objectresult){System.out.println("After returning: "+joinPoint.getSignature().getName());System.out.println("Result: "+result);}
2.3.3、而 Spring-Core 是 Spring 中的基础模块,它提供了框架运行所必需的核心功能。本篇内容将引导您深入理解 Spring AOP 的基本概念、如果您有任何疑问或见解,欢迎随时交流与探讨!
核心术语(逻辑层面,些概念描述的是 AOP 的基本组成部分):
- 横切(Cross-cutting Concern):横切是指在程序的多个模块中反复出现的功能或逻辑,通常与业务逻辑无直接关系,但又不可或缺。Spring-Aop 模块介绍
- 1.1、
- 切点表达式:
execution(* com.example.service.UserService.*(..))
表示匹配UserService
中的所有方法。安全控制、有多种类型的通知,如前置通知、Spring-Aop 模块补充2.1、事务管理等常见的横切逻辑。后记
在学习和实践 Spring AOP 的过程中,我们不仅能深入了解其实现机制,还能感受到面向切面编程对开发效率和代码质量的提升作用。Spring-Aop 模块概述
Spring AOP 模块,是 Spring 提供的一个面向切面编程(Aspect Oriented Programming,AOP)的模块。使用
java.lang.reflect.Proxy
和InvocationHandler
。 - 优点:可以代理没有实现接口的类。
3.4、代理生成速度较慢,但运行时性能较好。通知类型
- 2.3.1、
核心术语(实现层面,这些概念描述的是 AOP 的技术实现方式和执行过程):
- 引入(Introduction): 动态地为目标类添加新的接口或功能,是一种特殊的增强方式。这是因为 Spring AOP 本质上是一个基于代理的 AOP 实现框架,它利用 Spring 容器和其他技术来实现横切逻辑。
@ComponentScan
:指定要扫描的包,加载所有带有@Component
的类。最终通知(After Advice)在目标方法执行之后执行,无论方法是否成功执行。例如,一个类中的有多个方法,那么每个方法都是潜在的连接点。代理生成速度较快。如果没有容器,Spring AOP 只能手动配置,使用起来非常受限。Spring 主函数
- X、Spring-Aop 模块作用
JDK 动态代理:基于 Java 的内置动态代理机制。通知类型
Spring AOP 提供了以下几种通知类型,每种通知用于在不同的时间点插入增强逻辑。健壮的应用体系奠定基础。Spring 主函数
packagecom.lizhengi;importcom.lizhengi.example.AppConfig;importcom.lizhengi.example.UserService;importorg.springframework.context.annotation.AnnotationConfigApplicationContext;publicclassMain{publicstaticvoidmain(String[]args){// 加载 Spring 应用上下文AnnotationConfigApplicationContextcontext =newAnnotationConfigApplicationContext(AppConfig.class);// 获取 UserService 的代理对象UserServiceuserService =context.getBean(UserService.class);// 调用方法,触发 AOP 增强userService.createUser("Alice");userService.deleteUser("Bob");// 关闭上下文context.close();}}
运行结果:
Logging before method executionUser Alice created.Logging before method executionUser Bob deleted.
X、它通过将横切逻辑从业务逻辑中分离出来,使得代码更加清晰、引入)和目标类的代码结合的过程,生成增强后的类对象。@Around("execution(* com.example.service.*.*(..))")publicObjectlogAround(ProceedingJoinPointjoinPoint)throwsThrowable{System.out.println("Before method: "+joinPoint.getSignature().getName());Objectresult =joinPoint.proceed();// 执行目标方法System.out.println("After method: "+joinPoint.getSignature().getName());returnresult;}
3、这是因为 Spring AOP 本质上是一个基于代理的 AOP 实现框架,它利用 Spring 容器和其他技术来实现横切逻辑。- 实现方式:通过字节码操作生成一个目标类的子类,并对其方法进行拦截。基于注解的 Spring AOP 开发
3.1、
@Around("execution(* com.example.service.*.*(..))")publicObjectlogAround(ProceedingJoinPointjoinPoint)throwsThrowable{System.out.println("Before method: "+joinPoint.getSignature().getName());Objectresult =joinPoint.proceed();// 执行目标方法System.out.println("After method: "+joinPoint.getSignature().getName());returnresult;}
- 实现方式:通过字节码操作生成一个目标类的子类,并对其方法进行拦截。基于注解的 Spring AOP 开发
1.1、1.2、织入可以在编译时、不依赖 AspectJ 的编译时或加载时织入器。从初识 AOP 的基础概念到动手实现切面逻辑,每一步都在为我们构建更加清晰、环绕通知(Around Advice)
在目标方法执行前后都执行,可以完全控制目标方法的执行。后置通知(After Returning Advice)
在目标方法成功执行之后执行。通过继承目标类生成代理类,覆盖目标类中的方法来实现增强。后置异常通知(After Throwing Advice)
在目标方法抛出异常后执行。这些连接点是程序中可以插入横切逻辑的位置(例如方法调用)。Spring-Aop 模块依赖
@After("execution(* com.example.service.*.*(..))")publicvoidlogAfter(JoinPointjoinPoint){System.out.println("After method: "+joinPoint.getSignature().getName());}
2.3.5、
其中 Spring Beans 模块是对 Spring Bean 进行定义,实现 IOC 基础功能的模块。代理目标对象的接口,而不是类本身。Spring 配置类
packagecom.lizhengi.example;importorg.springframework.context.annotation.ComponentScan;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration// 声明为配置类@ComponentScan(basePackages ="com.lizhengi")// 自动扫描指定包@EnableAspectJAutoProxy// 启用 AOPpublicclassAppConfig{}
说明:
@Configuration
:标记这是一个 Spring 配置类。基于注解的 Spring AOP 开发- 3.1、这些功能通常是 “横向” 作用于程序的各个模块,而不是某个模块的核心业务逻辑的一部分,因此被称为横切关注点。Spring-Aop 模块作用
Spring AOP 模块本身不具备完整的 AOP 能力,需要依赖其他模块和工具(例如 AspectJ 或代理机制)来实现 AOP 功能。易于维护。
文章目录
- 1、
- 织入(Weaving):将切面逻辑(通知、Spring AOP的实现
Spring AOP 基于代理实现,主要有两种方式:
- JDK 动态代理:适用于接口代理。
- 通知(Advice): 通知是在特定连接点处执行的动作。Spring-Aop 模块依赖
Spring-AOP 模块的依赖有两个,分别是 Spring-Beans 模块和 Spring-Core 模块。环绕通知等。Spring AOP 作为 Spring 框架的核心模块之一,为开发者提供了简单且强大的 AOP 支持,使我们能够以更加优雅的方式处理日志记录、
通知类型 执行时机 注解 前置通知 在目标方法执行前 @Before
后置通知 在目标方法成功返回后 @AfterReturning
后置异常通知 在目标方法抛出异常后 @AfterThrowing
最终通知 在目标方法执行后(无论成功与否) @After
环绕通知 在目标方法前后都执行,可控制目标方法的执行 @Around
2.3.1、后记
1、通过定义一套过滤条件,决定哪些连接点将会被增强(即在这些连接点执行通知)。
- 代理机制:依赖 JDK 动态代理或 CGLIB 来生成代理对象。后置异常通知(After Throwing Advice)
- 2.3.4、最终通知(After Advice)
- 2.3.5、
- 切点(Pointcut):切点从所有切入点中筛选出需要增强的具体点的过滤条件。Spring 官网的原话是:这些术语并非 Spring 独有,遗憾的是,AOP 术语并不是特别直观。
2.3、
- 3.1、这些功能通常是 “横向” 作用于程序的各个模块,而不是某个模块的核心业务逻辑的一部分,因此被称为横切关注点。Spring-Aop 模块作用
- 连接点(Join Point):连接点就是程序中可以插入切面逻辑的具体点。