多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
案例源码:https://gitee.com/flymini/codes03/tree/master/learn-springpgm **** [TOC] # 1. 前置增强 **1. 前置增强配置** ```xml <aop:config> <aop:pointcut id="getUsername1Point" expression="execution(public void getUsername1(String))"/> <aop:aspect ref="aspectLogger"> <aop:before method="printLogBefore" pointcut-ref="getUsername1Point"/> </aop:aspect> </aop:config> ``` **2. 增强函数** ```java public void printLogBefore(JoinPoint jPoint) { System.out.println("\n------增强函数的输出------" + "\n增强方式:前置增强" + "\n目标对象:" + jPoint.getTarget() + "\n目标函数:" + jPoint.getSignature().getName() + "\n目标函数的参数:" + Arrays.toString(jPoint.getArgs())); } ``` **3. 测试结果,前置增强函数的输出要在目标函数的前面** ``` ------增强函数的输出------ 增强方式:前置增强 目标对象:learn.springpgm.service.impl.UserServiceImpl@565f390 目标函数:getUsername1 目标函数的参数:[zhangsan] ------目标函数的输出------ [getUsername1]:zhangsan ``` * 前置增强先于目标函数运行。 * 无论目标函数是否发生异常,前置增强都正常执行,相当于放在`finally`语句块中执行。 * 不能获取目标函数的返回值。 # 2. 最终增强 **1. 最终增强配置** ```xml <aop:config> <aop:pointcut id="getUsername2Point" expression="execution(public void getUsername2(String))"/> <aop:aspect ref="aspectLogger"> <aop:after method="printLogAfter" pointcut-ref="getUsername2Point"/> </aop:aspect> </aop:config> ``` **2. 增强函数** ```java public void printLogAfter(JoinPoint jPoint) { System.out.println("------增强函数的输出------" + "\n增强方式:最终增强" + "\n目标对象:" + jPoint.getTarget() + "\n目标函数:" + jPoint.getSignature().getName() + "\n目标函数的参数:" + Arrays.toString(jPoint.getArgs())); } ``` **3. 测试结果,最终增强函数的输出要在目标函数的后面** ``` ------目标函数的输出------ [getUsername2]:zhangsan ------增强函数的输出------ 增强方式:最终增强 目标对象:learn.springpgm.service.impl.UserServiceImpl@78452606 目标函数:getUsername2 目标函数的参数:[zhangsan] ``` * 目标函数先于最终增强执行。 * 无论目标函数是否发生异常,最终增强都正常执行。 * 无法获取目标函数的返回值。 # 3. 异常增强 **1. 异常增强配置** ```xml <aop:config> <aop:pointcut id="getUsername3Point" expression="execution(public void getUsername3(String))"/> <aop:aspect ref="aspectLogger"> <!-- throwing: 目标函数发生的异常,如果发生异常则由printLogThrowing函数捕捉 --> <aop:after-throwing method="printLogThrowing" pointcut-ref="getUsername3Point" throwing="ex"/> </aop:aspect> </aop:config> ``` **2. 增强函数** ```java /** * @param ex ex的命名与 throwing="ex" 要一致 */ public void printLogThrowing(JoinPoint jPoint, Exception ex) { System.out.println("------增强函数的输出------" + "\n增强方式:异常增强" + "\n目标对象:" + jPoint.getTarget() + "\n目标函数:" + jPoint.getSignature().getName() + "\n目标函数的参数:" + Arrays.toString(jPoint.getArgs()) + "\n目标函数的异常:" + ex); } ``` **3. 测试结果,只有当目标函数发生异常时异常增强才执行** ``` ########## 没有发生异常的结果 ########### ------目标函数的输出------ [getUsername3]:zhangsan ########## 发生异常的结果 ########### ------增强函数的输出------ 增强方式:异常增强 目标对象:learn.springpgm.service.impl.UserServiceImpl@c667f46 目标函数:getUsername3 目标函数的参数:[null] 目标函数的异常:java.lang.RuntimeException: 用户名不能为空 java.lang.RuntimeException: 用户名不能为空 at learn.springpgm.service.impl.UserServiceImpl.getUsername3(UserServiceImpl.java:30) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ``` * 只有在目标函数发生异常时才执行。 * 目标函数先于异常增强执行。 * 不能获取目标函数的返回值。 # 4. 后置增强 **1. 后置增强配置** ```xml <aop:config> <aop:pointcut id="getUsername4Point" expression="execution(public String getUsername4(String))" /> <aop:aspect ref="aspectLogger"> <!-- returning: 获取目标函数的返回值,并发送到printLoReturning方法中--> <aop:after-returning method="printLogReturning" pointcut-ref="getUsername4Point" returning="result" /> </aop:aspect> </aop:config> ``` **2. 增强函数** ```java /** * @param result result的命名与 returning="result" 要一致 */ public String printLogReturning(JoinPoint jPoint, Object result) { System.out.println("------增强函数的输出------" + "\n增强方式:后置增强" + "\n目标对象:" + jPoint.getTarget() + "\n目标函数:" + jPoint.getSignature().getName() + "\n目标函数的参数:" + Arrays.toString(jPoint.getArgs()) + "\n目标函数的返回值:" + result); return "add-" + result; } ``` **3. 测试结果,可以获取目标函数的返回值** ``` ------目标函数的输出------ [getUsername4]:zhangsan ------增强函数的输出------ 增强方式:后置增强 目标对象:learn.springpgm.service.impl.UserServiceImpl@19976a65 目标函数:getUsername4 目标函数的参数:[zhangsan] 目标函数的返回值:[getUsername4]:zhangsan ``` * 只有目标函数不发生异常时才执行。 * 目标函数先于后置增强执行。 * 可以获取目标函数的返回值,但不能修改目标函数的返回值,如果目标函数返回`void`,则 result 为`null`。 # 5. 环绕增强 **1. 环绕增强配置** ```xml <aop:config> <aop:pointcut id="getUsername5Point" expression="execution(public String getUsername5(String))"/> <aop:aspect ref="aspectLogger"> <aop:around method="printLogAround" pointcut-ref="getUsername5Point"/> </aop:aspect> </aop:config> ``` **2. 增强方法** ```java /** * @param jPoint ProceedingJoinPoint接口是JoinPoint的子接口,它只能用在环绕增强中 * @return 环绕增强函数返回的值将作为目标函数的返回值 */ public String printLogAround(ProceedingJoinPoint jPoint) throws Throwable { Object[] args = jPoint.getArgs(); System.out.println("------增强函数的输出------" + "\n增强方式:环绕增强" + "\n目标对象:" + jPoint.getTarget() + "\n目标函数:" + jPoint.getSignature().getName() + "\n目标函数的参数:" + Arrays.toString(jPoint.getArgs())); jPoint.proceed(args); return "[printLogAround]-" + args[0]; } ``` **3. 测试结果,成功修改了目标函数的返回值** ``` ------增强函数的输出------ 增强方式:环绕增强 目标对象:learn.springpgm.service.impl.UserServiceImpl@a1f72f5 目标函数:getUsername5 目标函数的参数:[zhangsan] ------目标函数的输出------ 本应该返回值为:[getUsername5]:zhangsan 增强后返回值为:[printLogAround]-zhangsan ``` * 环绕增强在目标函数前后都执行。 * 环绕增强函数的返回值作为目标函数的返回值,即增强方法可以改变目标函数的返回值(注意:增强并不能获取目标函数的返回值,但能修改)。 * 如果增强函数返回值为`void`,则目标函数的返回值为`null`。