注意:本文章只是参照对大佬SpringBoot使用AOP详解的简单个人总结,如需要详细讲解,请点击链接
1. AOP的相关概念
-
切面 (Aspect):在AOP中,切面是一个类,里面有一些方法,这些方法被称为通知(Advice),用于在特定的时机对目标对象的方法进行增强。
-
切入点 (Pointcut):切入点是一种规则,用于定位在应用程序中哪些类、哪些方法需要进行拦截,从而实现对目标方法的增强。Spring AOP中使用execution表达式来定义切入点。
-
通知 (Advice):通知是切面中的一个方法,用于在目标方法的执行过程中插入额外的功能,如前置通知、后置通知、返回通知、异常通知等。
-
环绕通知 (Around):环绕通知是一种特殊的通知,它可以在目标方法的执行前后都进行额外的处理。在环绕通知中,可以获取目标方法的输入参数,并可以决定是否执行目标方法,甚至可以决定目标方法的返回值。
-
前置通知 (Before):前置通知是在目标方法执行前执行的通知,可以用于在目标方法执行前进行一些数据验证或者安全检查。
-
后置通知 (After):后置通知是在目标方法执行后执行的通知,无论目标方法是否发生异常,都会执行。
-
返回通知 (AfterReturning):返回通知是在目标方法执行成功并返回值后执行的通知,可以获取目标方法的返回值。
-
异常通知 (AfterThrowing):异常通知是在目标方法执行抛出异常后执行的通知,可以获取目标方法的异常信息。
-
连接点 (JoinPoint):在AOP中,连接点是指那些被拦截到的方法,可以在连接点上进行增强。
2. execution表达式
execution(<修饰符模式>? <返回类型模式> <方法名模式>(<参数模式>) <异常模式>?)
- 访问修饰符、异常类型可以省略,其余都是必填的
- 方法参数,..代表所有参数
- 类路径中,..代表多层路径,包括当前包的类和子包的类
// 所有方法
execution(* *..*(..))
// 指定参数,即入参本身的类型,不能放其接口、父类
execution(* *..*(java.lang.String, java.lang.String)
// 指定方法前缀
execution(* *..*.prefix*(..))
// 指定方法后缀
execution(* *..*.*suffix(..))
// 组合,增强所有方法,但是去掉指定前缀和指定后缀的方法
execution(* *..*(..)) && (!execution(* *..prefix*(..)) || !execution(* *..*suffix(..)))
3. 演示案例(前置通知)
3.1. 引入依赖
<!-- 主要是这个依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
3.2. 需要被增强的方法(注解@Component)
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class TestAOP {
public void test(){
log.info("测试文本");
}
}
3.3. 切面(注解@Component和@Aspect)
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
@Slf4j
public class MyAspect {
@Pointcut("execution(* com.example.aspect.TestAOP.*(..))")
public void myPointCut(){}
@Before("myPointCut()")
public void before(){
log.info("前置通知");
}
}
3.4. 测试
@SpringBootTest
class AspectDemoApplicationTests {
@Autowired
private TestAOP testAOP;
@Test
void before(){
testAOP.test();
}
}