ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

交叉业务:AOP 要解决的核心问题

交叉业务:AOP 要解决的核心问题 交叉业务AOP 要解决的核心问题一、什么是交叉业务交叉业务更标准的叫法是横切关注点Cross-Cutting Concerns。它指的是那些不属于某个具体业务逻辑却散布在多个业务模块中、被反复调用的通用逻辑。比如日志记录、事务控制、权限校验、性能监控、缓存处理、异常统一处理。这些逻辑几乎每个业务方法都需要但它们本身又不是“用户注册”“下单支付”这类核心业务。核心业务回答的是“这个功能要做什么”交叉业务回答的是“这个功能在运行时还需要什么额外保障”。二、交叉业务带来的问题假设一个 Service 里有多个业务方法每个方法都要写日志、开事务、检查权限publicvoidregister(Useruser){log.info(开始注册用户user.getName());// 日志TransactiontxtransactionManager.begin();// 事务try{if(!currentUser.hasPermission(user:add)){// 权限thrownewPermissionDeniedException();}userDao.save(user);// 核心业务tx.commit();log.info(注册成功);}catch(Exceptione){tx.rollback();log.error(注册失败,e);throwe;}}publicvoidupdateUser(Useruser){log.info(开始更新用户user.getName());// 同样的日志TransactiontxtransactionManager.begin();// 同样的事务try{if(!currentUser.hasPermission(user:update)){// 同样的权限thrownewPermissionDeniedException();}userDao.update(user);// 核心业务tx.commit();log.info(更新成功);}catch(Exceptione){tx.rollback();log.error(更新失败,e);throwe;}}这里真正的业务逻辑只有userDao.save(user)或userDao.update(user)一行其他全是交叉业务。问题很明显代码重复每个方法都要写一遍日志、事务、权限。耦合严重业务代码和通用逻辑混在一起改日志格式要改所有方法。维护困难新增一个方法就要复制一遍模板代码容易漏掉某个步骤。可读性差核心业务被淹没在大量非业务代码中。这种代码结构叫做代码纠缠Code Tangling和代码散落Code Scattering。交叉业务散落在各个模块里和核心业务纠缠在一起。三、AOP 如何解决交叉业务AOP 的思路是把交叉业务从核心业务中抽离出来放到独立的切面Aspect里通过动态代理在运行时织入。抽离后业务方法只剩下核心逻辑ServicepublicclassUserService{TransactionalLog(注册用户)RequiresPermission(user:add)publicvoidregister(Useruser){userDao.save(user);// 只有核心业务}TransactionalLog(更新用户)RequiresPermission(user:update)publicvoidupdateUser(Useruser){userDao.update(user);// 只有核心业务}}日志、事务、权限的实现都在各自的切面里AspectComponentpublicclassLogAspect{Around(annotation(log))publicObjectlog(ProceedingJoinPointpjp,Loglog)throwsThrowable{System.out.println(开始log.value());Objectresultpjp.proceed();System.out.println(完成log.value());returnresult;}}AspectComponentpublicclassTransactionAspect{Around(annotation(org.springframework.transaction.annotation.Transactional))publicObjecttransaction(ProceedingJoinPointpjp)throwsThrowable{// 开启事务、提交、回滚}}AspectComponentpublicclassPermissionAspect{Before(annotation(requiresPermission))publicvoidcheck(RequiresPermissionrequiresPermission){// 权限校验}}业务代码干净了交叉业务集中管理了修改日志格式只需要改LogAspect一个地方。四、常见的交叉业务类型交叉业务说明Spring 中的实现日志记录记录方法调用、参数、返回值自定义切面事务管理开启、提交、回滚事务Transactional权限校验方法执行前检查权限PreAuthorize、自定义切面缓存查询缓存、更新缓存Cacheable、CacheEvict性能监控统计方法执行耗时自定义切面异常处理统一捕获、转换、记录异常ControllerAdvice、自定义切面限流控制方法调用频率自定义切面幂等保证方法重复调用结果一致自定义切面五、交叉业务和核心业务的关系对比维度核心业务交叉业务关注点业务规则、数据处理通用保障、非功能性需求变化频率随需求变化相对稳定适用范围特定模块或方法多个模块、多个方法代码位置Service 方法内部切面中是否可复用低业务相关高通用典型例子注册、下单、支付日志、事务、权限核心业务是“做什么”交叉业务是“怎么做才安全、可追踪、可控制”。两者关注点不同但目标一致让系统正确、稳定、可维护。六、AOP 处理交叉业务的关键点切点要精确用execution、annotation等表达式明确指定哪些方法需要增强。切点写得太宽会拦截不必要的方法写得太窄会漏掉需要增强的方法。通知类型要选对前置校验用Before事务和缓存用Around异常处理用AfterThrowing。注意内部调用失效同一个类中方法 A 调用方法 BB 的切面不会生效。需要注入自身代理或使用AopContext.currentProxy()。避免切面嵌套过深多个切面叠加时执行顺序由Order控制。顺序不对可能导致事务和缓存的行为不符合预期。七、总结交叉业务是 AOP 要解决的核心问题。它指的是那些散布在多个业务模块中、与核心业务无关却又必不可少的通用逻辑如日志、事务、权限、缓存、监控。维度说明标准叫法横切关注点Cross-Cutting Concerns核心问题代码散落、代码纠缠、重复、难维护解决方式AOP 抽离到切面动态代理织入常见类型日志、事务、权限、缓存、监控、异常业务代码只保留核心业务逻辑切面代码集中管理交叉业务注意事项切点精确、通知选对、内部调用失效理解交叉业务就理解了 AOP 存在的意义。AOP 不是为了炫技而是为了把那些“每个方法都要做一遍”的事情从业务代码中拿出去统一放到一个地方管理。业务代码只负责业务交叉逻辑只负责保障各司其职。
返回列表