AOP
面向切片编程,将代码从业务逻辑中分离出来,通过切面进行声明式编程。
术语
- 连接点(Join Point):程序执行的某个特定位置,如类开始初始化、方法被调用等。
- 切入点(Pointcut):匹配连接点的表达式,即哪些连接点需要被织入通知。切入点可以是一个方法名,也可以是某个包下的所有方法。
- 通知(Advice):在连接点执行的操作,即切面代码。
- 切面(Aspect):通知和切入点的结合。
- 织入(Weaving):将切面应用到目标对象,生成代理对象的过程。
环境搭建
jdk 17 + Maven + Spring
依赖
xml
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>6.1.12</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>6.1.6</version>
</dependency>
</dependencies><dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>6.1.12</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>6.1.6</version>
</dependency>
</dependencies>注解
@Aspect
声明一个类为切面类。
@Before
在目标方法执行前执行。
@After
在目标方法执行后执行。
@AfterReturning
在目标方法正常返回后执行。
@AfterThrowing
在目标方法抛出异常后执行。
@Around
在目标方法执行前后执行。
@Pointcut
定义切入点表达式。
@Order
定义切面的优先级,数字越小优先级越高。
示例
java
@Aspect
@Component
@Order(2)
public class LogAspect {
// 公用切入点
@Pointcut("execution(* com.xhb.bean.CounterImpl.*(..))")
public void publicPoint(){}
// 前置通知
@Before("publicPoint()")
public void before(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("before " + methodName);
}
// 后置通知
@After("publicPoint()")
public void after(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("after " + methodName);
}
// 返回通知
@AfterReturning(value = "publicPoint()", returning = "result")
public void result(JoinPoint joinPoint, Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.println("result " + methodName + ", 结果:" + result);
}
// 异常通知
@AfterThrowing(value = "publicPoint()", throwing = "error")
public void error(JoinPoint joinPoint, ObjectError error) {
String methodName = joinPoint.getSignature().getName();
System.out.println("error " + methodName + ", 错误信息:" + error.getDefaultMessage());
}
}@Aspect
@Component
@Order(2)
public class LogAspect {
// 公用切入点
@Pointcut("execution(* com.xhb.bean.CounterImpl.*(..))")
public void publicPoint(){}
// 前置通知
@Before("publicPoint()")
public void before(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("before " + methodName);
}
// 后置通知
@After("publicPoint()")
public void after(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("after " + methodName);
}
// 返回通知
@AfterReturning(value = "publicPoint()", returning = "result")
public void result(JoinPoint joinPoint, Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.println("result " + methodName + ", 结果:" + result);
}
// 异常通知
@AfterThrowing(value = "publicPoint()", throwing = "error")
public void error(JoinPoint joinPoint, ObjectError error) {
String methodName = joinPoint.getSignature().getName();
System.out.println("error " + methodName + ", 错误信息:" + error.getDefaultMessage());
}
}