切面学习笔记

📅 发布时间:2026/8/11 6:20:39
切面学习笔记
SpringAOP 切面学习笔记一、AOP 基础概念1. 核心名词名词释义本项目对应切面 Aspect封装统一横切逻辑的类AspectComponentExportLimitAspect、SqlBase64Aspect切点 Pointcut匹配哪些类 / 方法需要增强execution 表达式execution(* ...exportFile(..))通知 Advice切点匹配后执行的增强逻辑Around 环绕通知最常用、Before、After连接点 JoinPoint被拦截的原始方法exportFile()、findDataCount()目标对象被代理的类Jar 包内 ControllerQuery_datasetController横切非业务主干、通用逻辑参数预处理、权限、导出条数校验、加解密、日志、限流。二、切面开发标准步骤实操流程创建切面类注册 SpringBeanComponent交给 SpringIOC 容器管理切面本质也是 Bean必须被扫描实例化Aspect标识当前类为 AOP 切面类AspectComponentpublicclassExportLimitAspect{}定义切点表达式 execution格式execution(返回值 全类名.方法名(参数))// 匹配Jar中Controller指定方法Around(execution(* com.mingyoutech.mybi.boot.query.dataset.controller.Query_datasetController.exportFile(..)))*任意返回值(..)任意参数个数、任意参数类型支持多切点||拼接方法1() || 方法2()里面的方法就是切点要处理的方法Around环绕通知-方法前后都会处理各种通知类型编写增强逻辑注解执行时机适用场景本项目使用Before目标方法执行前参数校验、预处理SqlBase64 解码参数AfterReturning方法正常返回后结果处理极少使用AfterThrowing方法异常抛出后异常统一记录异常日志After方法结束 (无论异常)资源释放关闭流Around环绕方法前后都可拦截可放行 / 终止参数校验、拦截终止请求导出条数限制✅本项目导出限制、Sql 解码全部使用Around 固定模板publicObjectaround(ProceedingJoinPointjoinPoint)throwsThrowable{// 1.前置增强逻辑Object[]argsjoinPoint.getArgs();//获取原始入参// 自定义拦截满足条件抛异常不走原方法if(超限){thrownewServiceException(QUERY0002);}// 放行原目标方法ObjectresultjoinPoint.proceed(args);// 后置增强逻辑returnresult;}joinPoint.proceed(args)执行原方法不调用 直接截断目标方法核心拦截原理。其他通知类型例子切点统一拦截com.mingyoutech.service..*.*(..)下所有 service 方法importorg.aspectj.lang.JoinPoint;importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.*;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.stereotype.Component;AspectComponentpublicclassAllAspectDemo{privatestaticfinalLoggerlogLoggerFactory.getLogger(AllAspectDemo.class);// 公共切点表达式复用Pointcut(execution(* com.mingyoutech.service..*.*(..)))publicvoidpointCut(){}/** * 1. Before 前置通知目标方法运行【之前】执行 * 拿不到返回值目标方法抛异常这个也已经执行过了 */Before(pointCut())publicvoidbefore(JoinPointjoinPoint){// 获取方法名、入参StringmethodNamejoinPoint.getSignature().getName();Object[]argsjoinPoint.getArgs();log.info(Before 前置通知方法名{}入参{},methodName,args);}/** * 2. AfterReturning 返回通知方法【正常执行完毕返回后】执行 * ⚠️ 如果目标方法抛出异常此方法不会跑 * returning retObj 用来接收目标方法的返回值 */AfterReturning(valuepointCut(),returningretObj)publicvoidafterReturning(JoinPointjoinPoint,ObjectretObj){log.info(AfterReturning 返回通知拿到返回值{},retObj);// 这里可以读取返回值但**不能修改返回值**// 注意AfterReturning只能读取无法改变上层的返回结果想修改返回只能用Around}/** * 3. AfterThrowing 异常通知目标方法抛出异常的时候才执行 * throwing ex 接收抛出的异常对象 */AfterThrowing(valuepointCut(),throwingex)publicvoidafterThrowing(JoinPointjoinPoint,Throwableex){log.error(AfterThrowing 异常通知捕获异常,ex);}/** * 4. After 最终通知相当于finally * ✅不管方法正常返回 OR 抛出异常一定会执行 * 拿不到返回值、拿不到异常做资源释放、记录日志 */After(pointCut())publicvoidafter(JoinPointjoinPoint){log.info(After 最终通知一定会执行);}/** * 5. Around 环绕通知功能最全包裹目标方法 * ProceedingJoinPoint 只能用在Around * 可以控制要不要执行原方法、修改入参、修改返回值、捕获异常 */Around(pointCut())publicObjectaround(ProceedingJoinPointjoinPoint)throwsThrowable{log.info(Around 环绕目标方法执行【之前】);Object[]argsjoinPoint.getArgs();Objectresult;try{// 执行原始目标方法resultjoinPoint.proceed(args);log.info(Around 环绕方法正常执行完成原始返回值{},result);// ✅环绕独有的能力修改返回值替换上层返回// result R.success(切面修改后的返回);}catch(Throwablee){log.error(Around 环绕捕获业务异常,e);// 可以选择继续抛出异常 或者 返回自定义对象throwe;}finally{log.info(Around 环绕finally块无论成功失败都执行);}log.info(Around 环绕返回处理后结果);returnresult;}}执行顺序目标方法抛出异常1. Around 前置部分 2. Before 3. 【执行业务目标方法】 4. Around 拿到proceed返回之后的代码 5. AfterReturning 6. After 7. Around return执行顺序目标方法抛出异常1. Around 前置部分 2. Before 3. 【执行业务目标方法 → 抛出异常】 4. Around catch块执行 5. AfterThrowing 6. After ⚠️ AfterReturning 不会执行三、切面使用时机什么时候选用 AOP适合使用 AOP 场景横向公共逻辑参数统一预处理SqlBase64 解码项目现有切面、参数脱敏、参数格式转换接口拦截校验导出条数上限校验、接口访问白名单、权限拦截、防重复提交全局通用处理接口耗时统计、统一日志记录、全局异常捕获多接口复用规则同一个校验规则作用在多个接口findDataCountexportFile 双接口导出校验四、开发注意事项高频踩坑点1、切点相关拦截 Jar 包内类全限定类名必须写完整包路径不能简写必须开启proxyTargetClasstrue参数下标固定args[下标]严格对应接口参数顺序接口修改参数顺序切面同步出错// exportFile(HttpServletResponse response,String jdbcid,String format,Map param)args[0]response、args[1]jdbcid、args[3]param不要用this内部调用同类中 A 方法调用 B 方法B 方法切面无法拦截AOP 代理失效2、入参空指针问题获取 param 前先判空if(param!nullparam.containsKey(queryid))3、SpringBean 注入切面必须Component否则 Spring 不实例化、切面不生效final 修饰成员变量强制构造注入避免空指针Jar 中的 Service 可以正常注入SpringIoC 可扫描第三方 Jar 的 Service。4、Around 关键注意proceed()只能调用一次多次调用会重复执行原接口抛出异常直接终止接口和业务全局异常处理器联动若需要修改入参修改args数组元素proceed(新args)传入修改后的参数。5、事务失效切面和事务注解 Transactional 顺序AOP 外层、事务内层切面抛异常会触发事务回滚。五、速记总结切面三板斧ComponentAspect 切点表达式 Around 通知拦截 JarproxyTargetClasstrue多切面排序OrderAround 核心proceed 放行、抛异常拦截公共通用逻辑用 AOP私有业务写在方法内。