ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Spring 03:AOP与事务管理

Spring 03:AOP与事务管理 引言在Spring框架中AOP面向切面编程和事务管理是两大核心功能。AOP通过代理模式实现方法增强事务管理则确保数据操作的原子性。本文将结合核心概念、工作流程和实际案例全面解析这两项技术。一、AOP核心概念与工作流程一AOP的核心概念概念AOP(Aspect Oriented Programming)面向切面编程一种编程范式作用在不惊动原始设计的基础上为方法进行功能增强核心概念代理ProxySpringAOP的核心本质是采用代理模式实现的连接点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 容器进行管理 做beanService的增强a spring 容器启动b 读取切入点pointcutc 初始化bean (创建代理对象)d 获取bean (已经增强的方法)二、AOP通知类型与应用一核心注解注解作用使用位置必要参数注意事项EnableAspectJAutoProxy启用Spring AOP代理机制配置类上方proxyTargetClassexposeProxy必须添加才能启用AOPAspect声明类为切面容器切面类上方-需配合Component使用Pointcut定义方法切入点空方法上方表达式字符串方法体必须为空EnableAspectJAutoProxy配置类启用AOPConfiguration EnableAspectJAutoProxy( // 核心启用注解 proxyTargetClass true, // 强制使用CGLIB代理 exposeProxy true // 暴露代理对象(AopContext.currentProxy()) ) ComponentScan(com.example.service) public class AppConfig { // 配置类其他内容... }AspectComponent- 声明切面类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方法/类/接口注解业务层方法/类/接口propagationisolationtimeoutrollbackFornoRollbackFor声明事务属性标记方法需要事务管理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); // 独立事务记录日志 } }
返回列表