【AOP是什么, springboot如何整合AOP】
主要是为了记录自己复习时候的知识点方便自己后面查看如果大家有问题可以留言一起讨论。概念将横切关注点cross-cutting concerns从业务逻辑中分离出来以提高代码的模块化、可重用性和可维护性。把通用、重复的非业务代码日志、权限校验、事务、性能监控抽离出来单独维护核心作用横向抽取重复代码纵向执行业务逻辑Spring AOP 是基于动态代理实现的它能增强Spring 管理的 Bean 里的 任意方法不管这个方法来自接口、类、抽象类、普通类 —— 都能增强不是只能增强接口不是只能增强接口两种代理机制决定它能增强什么当前给的样例代码是基于jdk动态代理如果想在没有实现任何接口的类上加aop需要切换CGLIB代理模型切换方法是我自己没有切换过有报错自己百度下1.切面配置类加注解EnableAspectJAutoProxy(proxyTargetClass true) // 启用 CGLIB2.在application.properties里配置强制使用 CGLIB 代理推荐spring.aop.proxy-target-classtrue使用 JDK 动态代理默认spring.aop.proxy-target-classfalseSpring AOP 会自动选择用哪种代理① 目标类 实现了接口→ 使用 JDK 动态代理→ 依然是增强 类里的方法② 目标类 没有实现任何接口→ 使用 CGLIB 代理→ 直接继承类照样增强方法核心概念1.切面Aspect封装通用功能的类比如日志切面、权限切面2.通知Advice切面要执行的具体动作什么时候执行Before方法执行前After方法执行后无论是否异常AfterReturning方法正常返回后AfterThrowing方法抛出异常后Around环绕通知最强大前后都能增强3.切点Pointcut定义哪些方法需要被增强匹配规则4.连接点JoinPoint被匹配到的具体方法5.目标对象Target被增强的业务对象用户 -》 web - service - dao - 数据库在不修改目标方法源代码的前提下对请求链路上的目标方法进行操作对目标方法添加事务管理给目标方法添加访问权限控制对目标方法进行读写分离save/update/delete操作一个数据源操作方法是通过动态代理融合Java spring boot 服务引入依赖dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId/dependency编写业务代码就是自己的测试接口以在接口前加日志为示例核心步骤配置我们的aop切面类创建日志切面实现方法执行前打印日志,方法执行后打印日志,异常时打印异常信息,统计方法执行耗时注解Aspect声明一个切面类告诉spring这个类包含横切关注点如日志、事务等的逻辑spring会识别并处理这个类中的 AOP 配置Component 将这个类交给 Spring 容器管理 让 Spring 自动扫描并创建这个类的 Bean 实例不需要手动在配置文件中定义 BeanPointcut(“execution(* com.example.demo002.controller….(…))”)定义 切点表达式指定哪些方法会被拦截。: 第一个星号表示任意返回值类型com.example.demo002.controller…: 匹配该包及其子包下的所有类*: 匹配任意方法名(…): 匹配任意参数列表Before(“logPointCut()”): 前置通知在目标方法执行之前运行AfterReturning(pointcut “logPointCut()”, returning “result”): 后置返回通知在目标方法正常返回后执行方法成功执行并返回结果后如果抛异常则不执行参数: returning “result” 将方法的返回值绑定到参数 Object resultAfterThrowing(pointcut “logPointCut()”, throwing “ex”): 异常通知在目标方法抛出异常时执行 方法抛出异常时参数: throwing “ex” 将捕获的异常绑定到参数 Exception exAfter(“logPointCut()”): 最终通知无论方法是否异常都会执行方法执行完成后类似 try-catch-finally 中的 finallyAround(“logPointCut()”): 环绕通知最强大的通知类型可以控制方法的整个执行过程 包裹整个方法执行过程关键方法:proceedingJoinPoint.proceed() - 执行目标方法可以在前后添加自定义逻辑用途: 性能监控、事务管理、缓存、重试机制等注意: 必须返回 result否则调用方拿不到返回值根据具体场景选择注解针对方法的执行与否要选择Aroundpackagecom.example.demo002.aop;importorg.aspectj.lang.JoinPoint;importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.*;importorg.springframework.stereotype.Component;importjava.util.Arrays;/** * 日志切面类 * Aspect 声明这是一个切面 * Component 交给Spring容器管理 */AspectComponentpublicclassLogAspect{/** * 切点定义 * 匹配 com.example.demo.controller 包下所有类的所有方法 * 这是一个空方法仅用于定义切点 */Pointcut(execution(* com.example.demo002.controller..*.*(..)))publicvoidlogPointCut(){}// 1. 前置通知方法执行前 Before(logPointCut())publicvoiddoBefore(JoinPointjoinPoint){System.out.println( 【AOP前置通知】开始 );// 获取方法名StringmethodNamejoinPoint.getSignature().getName();// 获取参数Object[]argsjoinPoint.getArgs();System.out.println(调用方法methodName);System.out.println(方法参数Arrays.toString(args));System.out.println( 【AOP前置通知】结束 \n);}// 2. 后置返回通知方法正常执行完返回后 AfterReturning(pointcutlogPointCut(),returningresult)publicvoiddoAfterReturning(JoinPointjoinPoint,Objectresult){System.out.println(\n 【AOP后置返回通知】开始 );System.out.println(返回结果result);System.out.println( 【AOP后置返回通知】结束 );}// 3. 异常通知方法抛出异常时执行 AfterThrowing(pointcutlogPointCut(),throwingex)publicvoiddoAfterThrowing(JoinPointjoinPoint,Exceptionex){System.out.println(\n 【AOP异常通知】开始 );System.out.println(异常信息ex.getMessage());System.out.println( 【AOP异常通知】结束 );}// 4. 最终通知无论是否异常都会执行 After(logPointCut())publicvoiddoAfter(JoinPointjoinPoint){System.out.println(\n 【AOP最终通知】方法执行完毕 );}// 5. 环绕通知最强大可控制方法执行 Around(logPointCut())publicObjectdoAround(ProceedingJoinPointproceedingJoinPoint)throwsThrowable{longstartSystem.currentTimeMillis();// 执行目标方法ObjectresultproceedingJoinPoint.proceed();longendSystem.currentTimeMillis();System.out.println(\n 【AOP环绕通知】);System.out.println(方法执行耗时(end-start)ms);returnresult;}}4.启动类不需要更改Spring Boot 会自动配置 AOP无需手动开启可以直接开始测试啦。5.AOP 典型应用场景统一日志记录接口权限校验全局事务管理接口性能监控缓存控制全局异常统一处理总结AOP 核心抽取重复代码不修改业务代码实现功能增强Spring Boot 整合只需引入 aop-starter Aspect 注解5 种通知Before/After/AfterReturning/AfterThrowing/Around核心注解Aspect切面、Pointcut切点、Component交给 Spring 管理