本文主要是介绍SpringBoot整合AOP及使用案例实战,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《SpringBoot整合AOP及使用案例实战》本文详细介绍了SpringAOP中的切入点表达式,重点讲解了execution表达式的语法和用法,通过案例实战,展示了AOP的基本使用、结合自定义注解以...
一、 引入依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boandroidot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
二、切入点表达式详解
切入点表达式用于定义在哪些连接点应用增强,可以组合并使用execution、within 、 @annotation 、@within 、@target、args、bean这几种表达式。
本文只介绍最常用的execution表达式。
execution表达式语法:execution([修饰符] 返回类型 [声明类型].方法名(参数) [异常])
* :匹配任意数量的字符(除了包分隔符.) .. :匹配任意数量的字符(包括包分隔符.)或任意数量的参数 + :匹配指定类型的子类型
@ASPect @Component public class TestAop { // 1.匹配特定类的特定方法 @Pointcut("execution(public void com.example.demo.controller.AopTestController.testAop(..))") public void testAopMethod1() { } // 2.匹配特定类的特定方法,访问修饰符可以省略 @Pointcut("execution(void com.example.demo.controller.AopTestController.testAop(..))") public void testAopMethod2() { } // 3.匹配特定类的特定方法,返回值可以使用通配符 * 表示任意返回值 @Pointcut("execution(* com.example.demo.controller.AopTestController.testAop(..))") public void testAopMethod3() { } // 4.包名可以使用通配符表示任意包,但是有几级包就需要写几个 * @Pointcut("execution(* *.*.*.*.AopTestController.testAop(..))") public void testAopMethod4() { } // 5.包名可以使用 .. 表示当前包及其子包 @Pointcut("execution(* *..AopTestController.testAop(..))") public void testAopMethod5() { } // 6.类名和方法名都可以使用 * 来实现通配 @Pointcut("execution(* *..*.*(..))") public void testAopMethod6() { } // 7. 匹配特定接口的所有实现方法 @Pointcut("execution(* com.example.demo.controller.AopTestController+.*(..))") public void testAopMethod7() { } }
三、案例实战
1. AOP基本使用
① 待增强的业务代码:
@RestController
public class AopTestController {
@GetMapping("/testAop")
public Object testAop() {
return "testAop";
}
@GetMapping("/testAopException")
public Object testAopException() {
return 1 / 0;
}
}② AOP切面:
@Aspect
@Component
public class AopTestAspect {
@Pointcut("execution(public * com.example.demo.controller.AopTestController.testAop(..)) " +
"|| execution(public * com.example.demo.controller.AopTestController.testAopException(..))")
public void log() {
}
@Before("log()")
public void deBefore(JoinPoint joinPoint) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
System.out.println("URL : " + request.getRequestURL().toString());
System.out.println("HTTP_METHOD : " + request.getMethod());
System.out.println("CLASS_METHOD : " + joinPoint);
System.out.println("ARGS : " + Arrays.toString(joinPoint.getArgs()));
System.out.println("前置通知:方法执行前执行...");
}
//返回通知
@AfterReturning(returning = "result", pointcut = "log()")
public void doAfterReturning(Object result) {
System.out.println("返回通知:方法成功执行并返回后执行...");
Sysjstem.out.println("方法的返回值: " + result);
}
//异常通知
@AfterThrowing(throwing = "exception", pointcut = "log()")
public void doThrowing(JoinPoint joinPoint, Exception exception) {
System.out.println("异常通知:方法异常时执行...");
System.out.println("产生异常的方法:" + joinPoint);
System.out.println("异常种类:" + exception);
}
//后置通知
@After("log()")
public void doAfter(JoinPoint joinPoint) {
System.out.println("后置通知:最后且一定执行...");
}
}③ 控制台打印:


2. AOP结合自定义注解
① 自定义注解:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LogAnnotation {
String desc() default " ";
}② 待增强的业务代码:
@RestController
public class AopTestController {
@GetMapping("testAopAnnotation")
@LogAnnotation(desc = "测试注解类型:testAopAnnotation")
public Object testAopAnnotation() {
return "testAopAnnotation";
}
}③ AOP切面:
@Aspect
@Component
public class AopAnnotationTestAspect {
@Pointcut(value = "@annotation(com.example.demo.annotation.LogAjavascriptnnotation)")
public void logAction() {
}
@Before("logAction() && @annotation(logAnnotation)")
public void doBefore(JoinPoint joinPoint, LogAnnotation logAnnotation) {
System.out.println("前置通知:方法执行前执行...");
System.out.println("doBefore注解的值:" + logAnnotation.desc());
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
System.out.println("URL: " + attributes.getRequest().getRequestURL().toString());
}
@AfterReturning(returning = "result", pointcut = "logAction() && @annotation(logAnnotation)")
public void doAfterReturning(Object result, LogAnnotation logAnnotation) {
System.out.println("doAfterReturning注解的值:" + logAnnotation.desc());
System.out.println("返回通知:方法成功执行并返回后执行...");
System.out.println("方法的返回值: " + result);
}
@AfterThrowing(throwing = "exception", pointcut = "logAction() && @annotation(logAnnotation)")
public void doThrows(JoinPoint joinPoint, Exception exception, LogAnnotation logAnnotation) {
System.out.println("doThrows注解的值" + logAnnotation.desc());
System.out.println("异常通知:方法异常时执行...");
System.out.println("产生异常的方法:" + joinPoint);
System.out.println("异常种类:" + exception);
}
@After("logAction() && @annotation(logAnnotation)")
public void doAfter(JoinPoint joinPoint, LogAnnotation logAnnotation) {
System.out.println("doAfter注解的值:" + logAnnotation.desc());
System.out.println("后置通知:最后且一定执行...");
}
}④ 控制台打印:

3. 环绕通知
1. 非注解模式
① 待增强业务代码:
@RestController
public class AopTestController {
@GetMapping("/testAopAround")
public Object testAopjsAround() {
return "testAopAround";
}
}② AOP切面:
@Aspect
@Component
public class AopAroundTestAspect {
@Pointcut("execution(public * com.example.demo.controller.AopTestController.testAopAround(..))")
public void logAround() {
}
@Around("logAround()")
public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {
try {
Object[] args = proceedingJoinPoint.getArgs();
System.out.println("通知类中的aroundAdvice方法执行前...");
// 明确调用切入点方法
Object resValue = proceedingJoinPoint.proceed(args);
System.out.println("通知类中的aroundAdvice方法执行后...返回值:" + resValue);
return resValue;
} catch (Throwable e) {
System.out.println("通知类中的aroundAdvice方法执行异常...");
throw new RuntimeException(e);
} finally {
System.out.println("通知类中的aroundAdvice方法执行完成...");
}
}
}③ 控制台打印:

2. 注解模式
① 自定义注解:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LogAnnotation {
String desc() default "www.chinasem.cn ";
}② 待增强的业务代码:
@RestController
public class AopTestController {
@GetMapping("/testAopAroundAnnotation")
@LogAnnotation(desc = "测试注解类型:testAopAroundAnnotation")
public Object testAopAroundAnnotation(){
return "testAopAroundAnnotation";
}
}③ AOP切面:
@Aspect
@Component
public class AopAroundAnnotationTestAspect {
@Pointcut(value = "@annotation(com.example.demo.annotation.LogAnnotation)")
public void logAroundAnnotation() {
}
@Around("logAroundAnnotation() && @annotation(logAnnotation)")
public Object aroundAnnotationAdvice(ProceedingJoinPoint proceedingJoinPoint, LogAnnotation logAnnotation) {
try {
System.out.println("logAnnotation注解的值:" + logAnnotation.desc());
Object[] args = proceedingJoinPoint.getArgs();
System.out.println("通知类中的aroundAnnotationAdvice方法执行前...");
// 明确调用切入点方法
Object resValue = proceedingJoinPoint.proceed(args);
System.out.println("通知类中的aroundAnnotationAdvice方法执行后...返回值:" + resValue);
return resValue;
} catch (Throwable e) {
System.out.println("通知类中的aroundAnnotationAdvice方法执行异常...");
throw new RuntimeException(e);
} finally {
System.out.println("通知类中的aroundAnnotationAdvice方法执行完成...");
}
}
}④ 控制台打印:

到此这篇关于SpringBoot整合AOP及使用案例实战的文章就介绍到这了,更多相关SpringBoot整合AOP内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!
这篇关于SpringBoot整合AOP及使用案例实战的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!