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) 配置
posted @   月歌  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示