1 AOP简介
AOP:Aspect-Oriented Programming,面向切面编程
- 切入点(PointCut): 一组连接点的集合,它定义了切面的哪些方法应该被执行(即在哪些类、哪些方法上切入),通常是一个正则表达式
- 执行点(JoinPoint): 通过PointCut选取出来的集合中的具体的一个执行点,如,方法调用、异常抛出或对象创建等
- 通知(Advice): Aspect的具体行为,它定义了在JoinPoint上执行的操作。可分为前置(Before)、后置(After)、环绕(Around)、异常处理(Exception)和最终(Final)通知等
- 切面(Aspect): 一个模块化单元,它封装了与横切关注点相关的行为。切面 = PointCut + Advice。即在什么时候、什么地方、做什么
- 织入(Weaving): 把切面加入对象,并创建出代理对象的过程
2 Aspectj
2.1 通知(Advice)类型
顺序: @Around->@Before->方法执行->@AfterReturning/@AfterThrowing->@After->@Around
名称 | 说明 |
---|---|
前置通知(@Before) | PointCut前执行 |
后置通知(@AfterReturning) | PointCut正常返回结果后执行(异常时不执行) |
环绕通知(@Around) | PointCut前和后都执行 |
异常通知(@AfterThrowing) | PointCut抛出异常后执行(异常时执行) |
最终通知(@After) | PointCut后始终执行(正常和异常时都执行) |
2.2 示例
see: https://github.com/hi-cooper/cz-tutorials/tree/main/aspectj-demo
2.2.1 pom
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.20.1</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.20.1</version>
</dependency>
2.2.2 业务方法
package com.taiwii.aspectjdemo.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public void print() {
System.out.println("print()");
}
public void printThrowing() {
System.out.println("printThrowing()");
throw new RuntimeException("This is a RuntimeException");
}
}
2.2.3 AOP配置
package com.taiwii.aspectjdemo.aop;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Configuration;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Parameter;
import java.util.Arrays;
@Slf4j
@Aspect
@Configuration
public class AOPConfig {
@Pointcut("execution(* com.taiwii..service..*.*(..))")
public void pointCutMethod() {
}
@Before("pointCutMethod()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
System.out.println("doBefore");
}
@AfterReturning("pointCutMethod()")
public void doAfterReturning(JoinPoint joinPoint) throws Throwable {
System.out.println("doAfterReturning");
}
@Around("pointCutMethod()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
Object result = null;
try {
System.out.println("before doAround");
result = joinPoint.proceed();
System.out.println("after doAround");
} catch (Exception e) {
System.out.println("after doAround Exception");
throw e;
}
return result;
}
@AfterThrowing("pointCutMethod()")
public void doAfterThrowing(JoinPoint joinPoint) throws Throwable {
System.out.println("doAfterThrowing");
}
@After("pointCutMethod()")
public void doAfter(JoinPoint joinPoint) throws Throwable {
System.out.println("doAfter");
}
}
2.2.4 测试类
package com.taiwii.aspectjdemo.service;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
@Order(1)
public void testPrint() {
this.userService.print();
}
@Test
@Order(2)
public void testPrintThrowing() {
this.userService.printThrowing();
}
}