1. 什么是 AOP?
AOP(Aspect-Oriented Programming)面向切面编程,是一种编程范式,旨在将程序中的横切关注点(如日志、安全、事务)从业务逻辑中分离出来,进行统一管理。
- 切面(Aspect):模块化关注点,比如日志切面。
- 连接点(Join point):程序执行中的点,如方法调用。
- 通知(Advice):切面在连接点执行的动作。
- 切入点(Pointcut):定义在哪些连接点执行通知。
- 目标对象(Target Object):被代理的业务对象。
- 代理对象(Proxy):增强后的业务对象。
2. Spring AOP 的工作原理
- Spring 使用 动态代理(JDK代理或CGLIB代理)为目标对象创建代理。
- 代理对象在调用方法时,根据切入点匹配,执行对应通知。
- 通过切面和通知,实现方法增强。
3. Spring AOP 术语解析
术语 | 说明 |
---|
Aspect | 切面,包含通知和切点的模块化代码 |
Join Point | 连接点,程序执行的点(通常是方法) |
Pointcut | 切入点,定义一组连接点的表达式 |
Advice | 通知,切面执行的动作(前置、后置等) |
Target | 目标对象,业务逻辑对象 |
Proxy | 代理对象,增强目标对象的对象 |
4. Spring AOP 常见通知类型
通知类型 | 说明 |
---|
Before | 方法调用前执行 |
After | 方法调用后执行(无论是否异常) |
AfterReturning | 方法成功返回后执行 |
AfterThrowing | 方法抛异常后执行 |
Around | 环绕通知,包裹方法执行 |
5. 简单 Spring AOP 示例代码
5.1 定义切面类
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
@Aspect
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void beforeAdvice() {
System.out.println("方法执行前 - 记录日志");
}
@After("execution(* com.example.service.*.*(..))")
public void afterAdvice() {
System.out.println("方法执行后 - 释放资源");
}
@Around("execution(* com.example.service.*.*(..))")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕通知 - 方法执行前");
Object retVal = pjp.proceed(); // 调用目标方法
System.out.println("环绕通知 - 方法执行后");
return retVal;
}
}
5.2 业务类
package com.example.service;
public class UserService {
public void addUser() {
System.out.println("执行添加用户业务");
}
}
5.3 Spring 配置(基于注解)
<context:component-scan base-package="com.example"/>
<aop:aspectj-autoproxy/>
5.4 测试调用
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = ctx.getBean(UserService.class);
userService.addUser();
运行输出:
环绕通知 - 方法执行前
方法执行前 - 记录日志
执行添加用户业务
环绕通知 - 方法执行后
方法执行后 - 释放资源
6. Spring AOP 代理类型
代理类型 | 说明 | 适用情况 |
---|
JDK 动态代理 | 基于接口,代理实现接口的类 | 目标类实现接口 |
CGLIB 代理 | 基于子类,生成目标类的子类代理 | 目标类未实现接口 |
7. @Pointcut 复用切入点表达式
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethods() {}
@Before("serviceMethods()")
public void beforeAdvice() {
System.out.println("前置通知");
}
8. 常用切入点表达式示例
表达式 | 说明 |
---|
execution(* com.example..*.*(..)) | 匹配 com.example 包及子包的所有方法 |
within(com.example.service.*) | 匹配 com.example.service 包内所有类 |
args(java.lang.String) | 匹配参数是字符串的方法 |
9. 总结
- Spring AOP 用于解耦横切关注点,增强代码复用与维护性。
- 通过切面(Aspect)、切入点(Pointcut)、通知(Advice)实现灵活控制。
- 代理机制分为 JDK 动态代理和 CGLIB 代理。
- 注解配置和 XML 配置都支持。
发表回复