通知类型
前置通知
aop:before
<aop:before method="printLog" pointcut-ref="pointcut">
</aop:before>
- method: 用于指定前置通知的方法名称
- pointcut: 用于指定切入点表达式
- pointcut-ref: 用于指定切入点表达式的作用
作用: 用于配置前置通知 出现位置: aop:aspect 的内部 执行时机: 前置通知永远都会在切入点方法(业务核心方法)执行之前执行 细节: 前置通知可以获取切入点方法的参数,并对其进行增强
异常通知
aop:after-throwing
<aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pointcut'>
</aop:after-throwing>
用于配置异常通知 出现的位置:它只能出现在 aop:aspect 标签内部 执行时机:异常通知的执行时机是在切入点方法(业务核心方法)执行产生异常之后,异常通知执行,如果切入点方法执行没有产生异常,则异常通知不会执行 细节:异常通知不仅可以获取切入点方法执行的参数,也可以获取切入点方法执行产生的异常信息
最终通知
用于指定最终通知。 出现的位置:它只能在 aop:aspect 标签内部
<aop:after method="afterPrintLog" pointcut-ref="pointcut">
</aop:after>
执行时机:最终通知的执行时机切入点方法(业务核心方法)执行完成之后,切入点方法返回之前执行,换句话说,无论切入点方法执行是否产生异常,它都会在返回之前执行。 细节:最终通知环节,可以获取到通知方法的参数,通知它可以做一些清理操作。
环绕通知
配置方式:
<aop:around method="aroundPrintLog" pointcut-ref="pt1"></aop:around>
作用: 用于配置环绕通知 出现位置: 只能出现在 aop:aspect标签的内部 属性:
- method: 用于指定环绕通知的方法名称
- pointcut: 用于指定切入点表达式
- pointcut-ref: 用于指定切入点表达式的引用
环绕通知,它是有别于面前四种通知类型外的特殊通知,前面四种通知(前置、后置、异常和最终)它们都是指定何时增强的通知类型。而环绕通知,它是Spring框架为我们提供的一种可以通过编码的方式,控制增强代码何时执行的通知类型。它里面借助ProceedingJoinPoint接口以及实现类,实现手动触发切入点方法的调用。
XML+注解方式
开启注解
<!-- 开启spring对注解aop的⽀持 -->
<aop:aspectj-autoproxy/>
示例代码
WzkLogUtils
/**
* WzkLogUtils
* @author wzk
* @date 11:26 2025/1/6
**/
@Component
@Aspect
public class WzkLogUtils {
/**
* 在引用切入点表达式的时候,必须是方法名+(),例如 pointcut()
* 在当前切面中使用,可以直接写方法名,在其他切面中使用的必须是全限定方法名
* @author wzk
* @date 11:28 2025/1/6
**/
@Pointcut("execution(* wzk.service.impl.*.*(..))")
public void pointcut() {
}
/**
* 前置通知
* @author wzk
* @date 13:50 2025/1/6
**/
@Before("pointcut()")
public void beforePrintLog(JoinPoint jp) {
Object[] args = jp.getArgs();
System.out.println("前置通知: beforePrintLog: " + Arrays.toString(args));
}
/**
* 异常通知
* @author wzk
* @date 13:50 2025/1/6
**/
@AfterThrowing(value = "pointcut()", throwing = "e")
public void afterThrowingPrintLog(JoinPoint joinPoint, Throwable e) {
System.out.println("后置通知: afterThrowingPrintLog: " + joinPoint.getSignature().getName() + " 异常: " + e.getMessage());
}
/**
* 后置通知
* @author wzk
* @date 13:50 2025/1/6
**/
@After("pointcut()")
public void afterPrintLog(JoinPoint joinPoint) {
System.out.println("后置通知: afterPrintLog: " + joinPoint.getSignature().getName());
}
/**
* 环绕通知
* @author wzk
* @date 13:50 2025/1/6
**/
@Around("pointcut()")
public Object aroundPrintLog(ProceedingJoinPoint proceedingJoinPoint) {
Object result = null;
try {
System.out.println("环绕通知: beforePrintLog: " + proceedingJoinPoint.getSignature().getName());
result = proceedingJoinPoint.proceed();
System.out.println("环绕通知: afterPrintLog: " + proceedingJoinPoint.getSignature().getName());
} catch (Throwable e) {
System.out.println("异常通知");
e.printStackTrace();
} finally {
System.out.println("最终通知");
}
return result;
}
public void printLog() {
System.out.println("WzkLogUtils: printLog");
}
}
注解模式
我们在使用注解驱动开发AOP时,我们要明确的是,是注解替换配置文件中的下面的这个配置:
<!--开启spring对注解aop的⽀持-->
<aop:aspectj-autoproxy/>
这个配置后续我们就不需要了,所以在 applicationContext.xml 中注释掉。
在配置类中使用如下注解进行替换上述配置:
/**
* WzkAopConfig
* @author wzk
* @date 13:59 2025/1/6
**/
@Configuration
@Component("wzk")
@EnableAspectJAutoProxy
public class WzkAopConfig {
}