Spring AOP
Java Spring AOP 动态代理详解及对比(静态代理、无代理)
1. 代理模式与 AOP
AOP(面向切面编程) 的核心是通过代理模式实现横切关注点(如日志、事务、权限)的模块化。代理模式为目标对象提供一个代理,通过代理对象间接访问目标对象,从而在不修改原始代码的前提下增强功能。
2. 静态代理
实现方式
- 手动编写代理类,代理类需实现与目标对象相同的接口或继承目标类。
- 代理类中调用目标对象的方法,并在方法前后添加增强逻辑。
优缺点
- 优点:简单直观,编译时即可确定代理关系
- 缺点:每个目标类需手动编写代理类,代码冗余;难以代理多个类或动态扩展
示例代码
// 接口
public interface UserService {
void saveUser();
}
// 目标类
public class UserServiceImpl implements UserService {
@Override
public void saveUser() {
System.out.println("保存用户");
}
}
// 静态代理类
public class UserServiceProxy implements UserService {
private UserService target;
public UserServiceProxy(UserService target) {
this.target = target;
}
@Override
public void saveUser() {
System.out.println("前置增强");
target.saveUser();
System.out.println("后置增强");
}
}
3. 动态代理
实现方式
- 动态代理在运行时动态生成代理类,无需手动编写代理类。Spring AOP 支持两种动态代理
- JDK 动态代理(基于接口) 和 CGLIB 动态代理(基于继承)。
JDK 动态代理
点击查看代码
public class JdkProxyHandler implements InvocationHandler {
private Object target;
public JdkProxyHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置增强");
Object result = method.invoke(target, args);
System.out.println("后置增强");
return result;
}
// 创建代理对象
public static Object createProxy(Object target) {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new JdkProxyHandler(target)
);
}
}
CGLIB 动态代理
点击查看代码
public class CglibProxyInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("前置增强");
Object result = proxy.invokeSuper(obj, args);
System.out.println("后置增强");
return result;
}
// 创建代理对象
public static Object createProxy(Class<?> targetClass) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetClass);
enhancer.setCallback(new CglibProxyInterceptor());
return enhancer.create();
}
}
优缺点
- 优点:无需手动编写代理类,减少冗余代码;支持代理多个类,灵活性高
- 缺点:JDK 代理需接口,CGLIB 无法代理 final 类或方法;运行时生成代理类,略微影响性能
4. 无代理 AspectJ 编译时织入
实现方式
- AspectJ 通过编译器或类加载期直接修改字节码,将切面逻辑织入目标类。
- 不依赖代理模式,直接修改目标类的代码。
优缺点
- 优点:支持更细粒度的切面(如字段、构造方法);性能更高(无代理调用开销)
- 缺点:需要额外配置编译器或类加载器(如使用 AspectJ 编译器)
5. 总结
小结
- 动态代理是 Spring AOP 的核心,平衡了灵活性和代码简洁性。
- 静态代理适合简单场景,但扩展性差。
- AspectJ 无代理方案适用于高性能需求,但需额外工具支持。
Spring AOP 的选择
- 若目标对象实现接口 → 使用 JDK 动态代理
- 若未实现接口 → 使用 CGLIB
- 强制使用 CGLIB:通过 @EnableAspectJAutoProxy(proxyTargetClass = true) 配置
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律