🚀 深入解析 Spring AOP 原理及源码
Spring AOP(Aspect-Oriented Programming,面向切面编程)是 Spring 框架的重要特性之一,它允许在不修改源代码的情况下,为方法添加增强功能,如日志记录、事务管理等。
本篇博客将从 AOP 的基本概念 入手,深入 底层原理 和 源码实现,带你彻底搞懂 Spring AOP。
🎯 1. 什么是 AOP?
AOP 主要用于 解耦业务逻辑 和 通用功能(如日志、事务、权限校验),它的核心思想是:
- 通过 切面(Aspect) 将 横切关注点(Cross-cutting concerns) 与主业务逻辑解耦。
- 在 方法执行的不同阶段(如执行前、执行后、异常时) 动态插入代码。
📌 1.1 Spring AOP 的基本概念
术语 | 解释 |
---|---|
切面(Aspect) | 封装多个通知的类,定义增强逻辑 |
通知(Advice) | 定义在切入点执行的具体操作(前置、后置、异常等) |
切入点(Pointcut) | 定义拦截哪些方法 |
连接点(JoinPoint) | 被拦截的方法(符合切入点规则的方法) |
代理(Proxy) | 通过 JDK 动态代理或 CGLIB 代理生成的增强对象 |
目标对象(Target) | 被代理的原始对象 |
🔥 2. Spring AOP 的实现方式
Spring AOP 主要使用 动态代理 来实现,支持以下两种方式:
- JDK 动态代理 (基于
java.lang.reflect.Proxy
,只能代理接口) - CGLIB 动态代理 (基于
net.sf.cglib
,代理具体类)
2.1 JDK 动态代理
适用于:目标类实现了接口
java
public interface UserService {
void register(String username);
}
public class UserServiceImpl implements UserService {
@Override
public void register(String username) {
System.out.println(username + " 注册成功!");
}
}
// 创建代理
UserService proxy = (UserService) Proxy.newProxyInstance(
UserServiceImpl.class.getClassLoader(),
new Class[]{UserService.class},
(proxyObj, method, args) -> {
System.out.println("方法执行前的增强");
Object result = method.invoke(new UserServiceImpl(), args);
System.out.println("方法执行后的增强");
return result;
}
);
proxy.register("张三");
2.2 CGLIB 动态代理
适用于:目标类没有实现接口
java
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserServiceImpl.class);
enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> {
System.out.println("方法执行前的增强");
Object result = proxy.invokeSuper(obj, args);
System.out.println("方法执行后的增强");
return result;
});
UserServiceImpl proxy = (UserServiceImpl) enhancer.create();
proxy.register("张三");
⚙️ 3. Spring AOP 的核心源码解析
Spring AOP 的核心实现依赖 ProxyFactory,具体流程如下:
- 获取目标对象(Target)
- 解析切面和通知(Advice)
- 生成代理对象(JDK 代理或 CGLIB 代理)
- 执行代理方法,触发增强逻辑
3.1 关键类分析
类名 | 作用 |
---|---|
ProxyFactory |
代理对象工厂,负责创建代理 |
AdvisedSupport |
AOP 配置管理,包含目标对象、切面、通知等信息 |
DefaultAopProxyFactory |
选择代理方式(JDK 代理或 CGLIB 代理) |
JdkDynamicAopProxy |
JDK 动态代理实现 |
CglibAopProxy |
CGLIB 代理实现 |
3.2 源码解析
当一个类被 AOP 代理时,Spring 会通过 ProxyFactory
创建代理:
java
ProxyFactory proxyFactory = new ProxyFactory(new UserServiceImpl());
proxyFactory.addAdvice(new MyMethodInterceptor());
UserService proxy = (UserService) proxyFactory.getProxy();
底层会判断:
- 如果目标类有接口 → 使用
JdkDynamicAopProxy
- 如果目标类没有接口 → 使用
CglibAopProxy
🚀 4. 如何自定义 AOP 切面?
Spring AOP 提供了 @Aspect
注解来定义切面:
java
@Aspect
@Component
public class LogAspect {
@Before("execution(* com.example.service.*.*(..))")
public void beforeMethod(JoinPoint joinPoint) {
System.out.println("执行前:" + joinPoint.getSignature());
}
@AfterReturning("execution(* com.example.service.*.*(..))")
public void afterMethod() {
System.out.println("执行后");
}
}
🔍 5. AOP 在实际项目中的应用
✅ 事务管理
Spring AOP 用于声明式事务管理:
java
@Transactional
public void saveOrder() {
orderDao.save();
}
✅ 日志记录
在方法执行前后记录日志:
java
@Around("execution(* com.example..*(..))")
public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("方法开始:" + joinPoint.getSignature());
Object result = joinPoint.proceed();
System.out.println("方法结束");
return result;
}
✅ 权限校验
在方法执行前检查权限:
java
@Before("execution(* com.example.service.*.*(..))")
public void checkPermission() {
if (!UserContext.hasPermission()) {
throw new RuntimeException("无权限访问");
}
}
📚 总结
- Spring AOP 通过动态代理(JDK 代理或 CGLIB 代理)实现方法增强。
- 底层主要依赖
ProxyFactory
,根据目标类是否有接口选择 JDK 代理或 CGLIB 代理。 - Spring AOP 常用于事务管理、日志记录、权限校验等场景。
- 自定义 AOP 需要使用
@Aspect
和@Around
、@Before
、@AfterReturning
等注解。
Spring AOP 是 Spring 核心组件之一,理解其底层原理,有助于在实际项目中更灵活地使用切面编程,提高代码的可维护性和扩展性。
如果你对 Spring AOP 还有其他疑问,欢迎在评论区交流! 🚀