概念
- Spring AOP - Aspect Oriented Programming 面向切面编程
- AOP的做法是将通用、与业务无关的功能抽象封装为切面类
- 切面可配置在目标方法的执行前、后运行,真正做到即插即用
- 可以在不修改源码的情况下对程序进行扩展
AOP配置过程——基于XML配置
0. 添加依赖创建配置文件
添加依赖-aspectjweaver
| <dependency> |
| <groupId>org.springframework</groupId> |
| <artifactId>spring-context</artifactId> |
| <version>5.2.25.RELEASE</version> |
| </dependency> |
| |
| |
| <dependency> |
| <groupId>org.aspectj</groupId> |
| <artifactId>aspectjweaver</artifactId> |
| <version>1.9.6</version> |
| </dependency> |
SpringAOP和AspectJ的关系
- Eclipse AspectJ,一种基于Java平台的面向切面编程的语言
- SpringAOP使用AspectJWeaver实现类与方法匹配
- SpringAOP利用代理模式实现对象运行时功能扩展
创建配置文件: 新增context和aop的xmlns
| <?xml version="1.0" encoding="UTF-8"?> |
| <beans xmlns="http://www.springframework.org/schema/beans" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| xmlns:aop="http://www.springframework.org/schema/aop" |
| xmlns:context="http://www.springframework.org/schema/context" |
| xsi:schemaLocation=" |
| http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd |
| http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd |
| http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> |
| |
| </beans> |
具体的schema可以在spring官网找到,步骤如下:




几个关键概念

1. 实现切面类/方法
- Aspect,切面,具体的可插拔组件功能类,通常一个切面只实现一个通用功能
- Target Class/Method:目标类、目标方法,指真正要执行与业务相关的方法
JoinPoint
- 连接点,切面运行过程中包含了目标类/方法元数据的对象

2. 配置Aspect Bean
3. 定义PointCut
- PointCut,切入点,使用execution表达式说明切面要作用在系统的哪些类上
- 使用execution表达式描述切面的作用范围

4. 配置Advice通知
- Advice,通知,说明具体切面的执行时机,Spring包含了五种不同类型的通知

Around Advice环绕通知
- 实现切面类/方法
ProceedingJoinPoint是JoinPoint的升级版,在原有功能外,还可以控制目标方法是否执行,需要强制返回目标方法返回值
| package com.EveX.spring.aop.aspect; |
| |
| import org.aspectj.lang.ProceedingJoinPoint; |
| |
| import java.text.SimpleDateFormat; |
| import java.util.Date; |
| |
| |
| public class MethodChecker { |
| public Object check(ProceedingJoinPoint pjp) throws Throwable { |
| try { |
| long stime = new Date().getTime(); |
| Object ret = pjp.proceed(); |
| long etime = new Date().getTime(); |
| long duration = etime - stime; |
| if(duration > 1000) { |
| String className = pjp.getTarget().getClass().getName(); |
| String methodName = pjp.getSignature().getName(); |
| SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss SS"); |
| String now = dateFormat.format(new Date()); |
| System.out.println("=====>" + now + ":" + className + "." + methodName + "(" + duration + "ms)<====="); |
| } |
| return ret; |
| } catch (Throwable e) { |
| System.out.println("Exception message:" + e.getMessage()); |
| throw e; |
| } |
| |
| } |
| } |
- 配置Aspect Bean
| <bean id="methodChecker" class="com.EveX.spring.aop.aspect.MethodChecker"></bean> |
- 定义PointCut
- 配置Advice通知
| <aop:config> |
| |
| <aop:pointcut id="pointcut" expression="execution(* com.EveX..*.*(..))"/> |
| |
| <aop:aspect ref="methodChecker"> |
| |
| <aop:around method="check" pointcut-ref="pointcut"></aop:around> |
| </aop:aspect> |
| </aop:config> |
AOP配置过程——基于注解配置
- 开启context包扫描初始化Ioc容器+启动Spring AOP注解模式
| <?xml version="1.0" encoding="UTF-8"?> |
| <beans xmlns="http://www.springframework.org/schema/beans" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| xmlns:aop="http://www.springframework.org/schema/aop" |
| xmlns:context="http://www.springframework.org/schema/context" |
| xsi:schemaLocation=" |
| http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd |
| http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd |
| http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> |
| |
| |
| <context:component-scan base-package="com.EveX"></context:component-scan> |
| |
| <aop:aspectj-autoproxy></aop:aspectj-autoproxy> |
| </beans> |
- 在切面类中添加注解
| package com.EveX.spring.aop.aspect; |
| |
| import org.aspectj.lang.ProceedingJoinPoint; |
| import org.aspectj.lang.annotation.Around; |
| import org.aspectj.lang.annotation.Aspect; |
| import org.springframework.stereotype.Component; |
| |
| import java.text.SimpleDateFormat; |
| import java.util.Date; |
| |
| |
| @Component |
| @Aspect |
| public class MethodChecker { |
| |
| @Around("execution(* com.EveX..*.*(..))") |
| public Object check(ProceedingJoinPoint pjp) throws Throwable { |
| try { |
| long stime = new Date().getTime(); |
| Object ret = pjp.proceed(); |
| long etime = new Date().getTime(); |
| long duration = etime - stime; |
| if(duration > 1000) { |
| String className = pjp.getTarget().getClass().getName(); |
| String methodName = pjp.getSignature().getName(); |
| SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss SS"); |
| String now = dateFormat.format(new Date()); |
| System.out.println("=====>" + now + ":" + className + "." + methodName + "(" + duration + "ms)<====="); |
| } |
| return ret; |
| } catch (Throwable e) { |
| System.out.println("Exception message:" + e.getMessage()); |
| throw e; |
| } |
| |
| } |
| } |
Spring AOP实现原理
Spring 基于代理模式实现功能动态扩展,包含两种形式:
- 目标类拥有接口,通过JDK动态代理实现功能扩展
- 目标类没有接口,通过CGLib组件通过继承的方式实现功能扩展
CGLib实现代理类:
- CGLib是运行时字节码增强技术
- AOP会在运行时生成目标继承类字节码的方式进行行为扩展
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效