news 2026/9/18 11:33:37

Spring 03:AOP与事务管理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring 03:AOP与事务管理

引言

在Spring框架中,AOP(面向切面编程)和事务管理是两大核心功能。AOP通过代理模式实现方法增强,事务管理则确保数据操作的原子性。本文将结合核心概念、工作流程和实际案例,全面解析这两项技术。

一、AOP核心概念与工作流程

(一)AOP的核心概念

概念:AOP(Aspect Oriented Programming)面向切面编程,一种编程范式

作用:在不惊动原始设计的基础上为方法进行功能增强

核心概念

代理(Proxy):SpringAOP的核心本质是采用代理模式实现的

连接点(JoinPoint):在SpringAOP中,理解为任意方法的执行

切入点(Pointcut):匹配连接点的式子,也是具有共性功能的方法描述

通知(Advice):若干个方法的共性功能,在切入点处执行,最终体现为一个方法

切面(Aspect):描述通知与切入点的对应关系

目标对象(Target):被代理的原始对象成为目标对象

(二)动态代理:AOP的基石

AOP底层基于动态代理实现,分为两种模式:

  • JDK动态代理:通过接口实现,生成com.sun.proxy.$Proxy0代理类

  • CGLIB代理:针对无接口的类,通过子类继承实现

代理模式的组成

  • 抽象主题(接口)

  • 真实主题(实现类)

  • 代理类(增强逻辑的载体)

    // JDK动态代理示例 public class JdkProxy implements InvocationHandler { private Object target; // 目标对象 public Object invoke(Object proxy, Method method, Object[] args) { System.out.println("前置增强"); Object result = method.invoke(target, args); System.out.println("后置增强"); return result; } }

    (三) AOP工作流程

    Spring容器启动时的AOP流程:

  • 加载Bean:初始化目标对象和通知类

  • 解析切入点:读取所有@Pointcut配置

  • 创建代理对象:匹配切入点的方法生成代理

  • 执行增强逻辑:调用代理对象方法时织入通知

Spring 容器进行管理 做bean(Service)的增强

a spring 容器启动
b 读取切入点(pointcut)
c 初始化bean (创建代理对象)
d 获取bean (已经增强的方法)

二、AOP通知类型与应用

(一)核心注解

注解作用使用位置必要参数注意事项
@EnableAspectJAutoProxy启用Spring AOP代理机制配置类上方proxyTargetClass
exposeProxy
必须添加才能启用AOP
@Aspect声明类为切面容器切面类上方-需配合@Component使用
@Pointcut定义方法切入点空方法上方表达式字符串方法体必须为空
@EnableAspectJAutoProxy配置类启用AOP
@Configuration @EnableAspectJAutoProxy( // 核心启用注解 proxyTargetClass = true, // 强制使用CGLIB代理 exposeProxy = true // 暴露代理对象(AopContext.currentProxy()) ) @ComponentScan("com.example.service") public class AppConfig { // 配置类其他内容... }
@Aspect+@Component- 声明切面类
@Aspect // 声明为切面类 @Component // 纳入Spring容器管理 public class SecurityAspect { // 切入点定义和通知方法将写在此类中 }
@Pointcut- 定义切入点表达式
@Aspect @Component public class LoggingAspect { // 定义service包下所有方法的切入点 @Pointcut("execution(* com.example.service.*.*(..))") public void serviceMethods() {} // 方法体必须为空! // 定义带@Audit注解的方法切入点 @Pointcut("@annotation(com.example.Audit)") public void auditedMethods() {} // 组合切入点:匹配service包中带@Audit注解的方法 @Pointcut("serviceMethods() && auditedMethods()") public void auditedServiceMethods() {} }

(二)五种通知类型

通知类型注解执行时机
前置通知@Before方法执行前
后置通知@After方法执行后(无论是否异常)
环绕通知@Around方法执行前后(需调用proceed()
返回后通知@AfterReturning方法正常返回后
异常通知@AfterThrowing方法抛出异常后
@Around("execution(* com.example.*.*(..))") public Object around(ProceedingJoinPoint pjp) throws Throwable { long start = System.currentTimeMillis(); Object result = pjp.proceed(); // 调用原始方法 long time = System.currentTimeMillis() - start; System.out.println("方法执行耗时:" + time + "ms"); return result; }

三、AOP切入点

切入点表达式是AOP的核心能力,它精确控制哪些方法需要被增强。掌握其语法和优化技巧是高效使用AOP的关键。

切入点表达式标准格式:动作关键字(访问修饰符 返回值 包名./接口名.方法名(参数)异常

)

execution(* com.mytest.service.*Service.*(..))
场景推荐表达式优势
业务层方法匹配execution(* com..service.*Service.*(..))精确匹配Service结尾的类
查询方法匹配execution(public java.util.List+ find*(..))明确返回集合类型
注解驱动切面@annotation(com.example.Audit)解耦业务逻辑
参数化切入点args(username) && @annotation(audit)同时获取参数和注解
  • 避免within(com.example..*)全包扫描(性能杀手)

  • 慎用*作为方法名首字符(如*Dao会匹配deleteDao

  • 使用+匹配子类时注意继承深度

四、Spring事务管理

(一)事务核心概念

  • PlatformTransactionManager:事务管理器接口

  • @Transactional:声明式事务注解

  • 事务传播行为:控制事务边界(如REQUIRED/REQUIRES_NEW

注解类型作用位置关键属性使用场景说明
@EnableTransactionManagement配置类注解配置类上方-Spring事务的总开关,无此注解事务管理不生效
@Transactional方法/类/接口注解业务层方法/类/接口propagation
isolation
timeout
rollbackFor
noRollbackFor
声明事务属性,标记方法需要事务管理
@EnableTransactionManagement- 配置类启用事务
@Configuration @EnableTransactionManagement // 核心开关 @PropertySource("classpath:jdbc.properties") @ComponentScan("com.example.service") public class AppConfig { @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { // 必须配置事务管理器 return new DataSourceTransactionManager(dataSource); } }
@Transactional- 声明式事务控制
@Service // 类级事务配置(所有方法默认REQUIRED传播行为) @Transactional(isolation = Isolation.READ_COMMITTED, timeout = 30) public class OrderService { // 方法级配置(覆盖类级设置) @Transactional( propagation = Propagation.REQUIRES_NEW, rollbackFor = PaymentException.class, noRollbackFor = ValidationException.class ) public void createOrder(Order order) { // 数据库操作1:库存扣减 inventoryService.deduct(order); // 数据库操作2:订单创建 orderDao.save(order); // 数据库操作3:支付记录 paymentService.record(order); } }
事务传播行为对照表
传播行为说明
REQUIRED默认值当前有事务则加入,无则新建(推荐写操作使用)
REQUIRES_NEW总是新建事务挂起当前事务并创建新事务(适用于日志记录等独立操作)
SUPPORTS支持当前事务有事务则加入,无则以非事务方式执行(适合查询方法)
NOT_SUPPORTED非事务执行挂起当前事务,以非事务方式执行
MANDATORY强制有事务必须在事务中调用,否则抛出异常
NEVER禁止事务必须在非事务环境下调用,否则抛出异常
NESTED嵌套事务当前有事务时创建保存点,可部分回滚(需JDBC 3.0驱动支持)

(二)转账案例中的事务应用

示例

@Configuration @EnableTransactionManagement // 开启事务管理 public class AppConfig { @Bean public PlatformTransactionManager transactionManager(DataSource ds) { return new DataSourceTransactionManager(ds); // JDBC事务管理器 } } @Service public class AccountService { @Transactional( rollbackFor = Exception.class, propagation = Propagation.REQUIRED ) public void transfer(String from, String to, double amount) { accountDao.deduct(from, amount); accountDao.add(to, amount); } }

(三) 事务传播行为解决日志记录问题

场景:转账无论成功与否都需记录日志

@Service public class LogService { // 始终开启新事务 @Transactional(propagation = Propagation.REQUIRES_NEW) public void logTransfer(String from, String to, double amount) { logDao.save("转账:" + from + "→" + to + " 金额:" + amount); } } // 在转账方法中调用 public void transfer(String from, String to, double amount) { try { accountService.transfer(from, to, amount); } finally { logService.logTransfer(from, to, amount); // 独立事务记录日志 } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 11:33:24

CCF CSP相邻数对:从暴力到哈希的序列处理优化之路

CCF CSP的第一题,向来是给考生"练手"和"送分"的。但说句实在话,很多人第一次考CCF,恰恰就栽在这道"送分题"上——不是不会做,而是读题太急,把"相邻数对"理解成了"数组里…

作者头像 李华
网站建设 2026/9/18 11:33:12

3D角色资源制作规范从文档到资产管线的自动化落地实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 11:32:53

手眼标定本质是坐标系契约:从锚点、单位到闭环验证

1. 为什么“手眼标定”总在反复推导却依然模糊?“手眼标定”这四个字,几乎每个做机器人、视觉引导、自动化装配的工程师都写过几十遍,也查过上百次资料。但奇怪的是,很多人直到第三个项目还在问:“到底A_T_B里的A和B哪…

作者头像 李华
网站建设 2026/9/18 11:31:28

国产DCS系统深度观察:选型、组态与替代落地全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 11:31:25

基于DeepSeek API构建对话式代码补全智能体实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 11:30:52

Python机器学习实战:Scikit-Learn学习路径与数据挖掘应用

数据挖掘与机器学习:Python机器学习软件包Scikit-Learn的学习与运用1. 内容整体设计与思路拆解1.1 为什么选择Scikit-Learn作为机器学习入门工具学习数据挖掘和机器学习,选对工具能少走很多弯路。我在实验室带新人这几年,发现一个规律&#x…

作者头像 李华