如果你是小白并且已经看过相关的aop的文章和概念,
但是没有合适的AOP Demo作为练习,那么这篇文章正好适合你。
你可以粘贴相关代码到你的idea中运行
概念:
1、连接点:类里面哪些方法可以被增强,这些方法称为连接点。
2、切入点:实际被增强的方法,称为切入点。 例如:被增加的权限判断的登录功能,登录功能称为切入点。
3、通知(增强):实际增强的逻辑部分称为通知(增强)。 例如:给登录的功能加一个权限判断,那个权限判断就是通知
4、切面:把通知应用到切入点的过程就是切面。他只是一个动作。 例如:把权限判断增加到登录的功能中。 通知有多类型:前置、后置、环绕(方法前后都会执行)、异常、最终(类似finally)通知。
执行顺序:
around > before > around > after > afterReturning
spring boot AOP 实战
1.引入依赖maven
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>spring-boot-aop-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<version>2.4.5</version>
<artifactId>spring-boot-starter-parent</artifactId>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
</project>
2.切入点controller
package aop.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AopController {
@GetMapping("/aopTest") //切入点
public String aopTest(){
System.out.println("方法输出:aopTest");
return "方法返回:aopTest";
}
}
2.定义一个切面类(也可说是通知类)
通知有五种类型,分别是:
前置通知(@Before):在目标方法调用之前调用通知
后置通知(@After):在目标方法完成之后调用通知
环绕通知(@Around):在被通知的方法调用之前和调用之后执行自定义的方法
返回通知(@AfterReturning):在目标方法成功执行之后调用通知
异常通知(@AfterThrowing):在目标方法抛出异常之后调用通知
代码中定义了三种类型的通知,使用@Before注解标识前置通知,打印“beforeAdvice...”,使用@After注解标识后置通知,打印“AfterAdvice...”,使用@Around注解标识环绕通知,在方法执行前和执行之后分别打印“beforeAround”。这样一个切面就定义好了,代码如下:
package aop.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
//切面类
@Component
@Aspect
public class AopAdvice {
@Pointcut("execution(* aop.controller.*.*(..))")
public void aopTestPoint(){
}
@Before("aopTestPoint()")
public void beforeAdvice(){
System.out.println("beforeAdvice.......");
}
@After("aopTestPoint()")
public void afterAdvice(){
System.out.println("afterAdvice.......");
}
//只会执行切入点的方法(aopTest),但是会导致切入点方法没有返回值,因他没有接受并返回proceed的方法的值,
//此时请求aopTest方法时postman输出为null,
//所以建议对于没有返回值的切入点,选择这个方式进行增强
@Around("aopTestPoint()")
public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("beforeAround");
try {
proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
//不仅会执行切入点的方法(aopTest),并且请求切入点方法时,可以选择改变返回值或者不改变返回值
//所以建议对于有返回值的切入点,选择这个方式进行增强
// @Around("aopTestPoint()")
// public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
// System.out.println("beforeAround");
// Object result = null ;
// try {
// 这两个结果只能打开一个
// result = proceedingJoinPoint.proceed(); //不改变切入点方法(aopTest)的返回值
// result = proceedingJoinPoint.proceed()+ "增强了"; //改变了切入点方法(aopTest)的返回值
// } catch (Throwable throwable) {
// throwable.printStackTrace();
// }
// return result; //返回切入点方法(aopTest)的值
// }
}
4.启动测试
代码结构如图所示:
运行SpringBootAopDemoApplication。使用postman或者浏览器都可以,我使用的是postman结果如下:
单独测试@Around(没有返回值的):
单独测试@Around(有返回值的):
测试包含before和after和around三种情况下的输出:
测试结果符合这个顺序:around > before > around > after > afterReturning