代理模式是 Java 设计模式中结构型模式的核心代表,更是 Spring AOP、事务管理、RPC 框架、日志拦截等核心技术的底层实现基石。理解 Java 代理的实现原理,不仅能掌握设计模式的实战应用,更能打通 Spring 等主流框架的底层逻辑。本文将从代理模式的核心思想出发,逐层拆解静态代理、JDK 动态代理、CGLIB 代理的实现细节、底层原理、优缺点及实战场景,最终带你掌握 AOP 技术的核心本质。

一、代理模式的核心本质

1.1 代理模式的定义

代理模式(Proxy Pattern):为目标对象提供一个代理对象,由代理对象控制对目标对象的访问。代理对象作为 “中间层”,既可以保护目标对象,也可以在不修改目标对象源码的前提下,对目标对象的功能进行扩展(如添加日志、权限校验、性能监控等)。

1.2 生活中的代理类比

  • 租房中介:你(客户端)不直接对接房东(目标对象),而是通过中介(代理对象)完成租房流程,中介会帮你筛选房源、审核资质(附加功能),最终完成租房(核心功能);
  • 明星经纪人:经纪人(代理)负责对接演出、洽谈费用(附加功能),明星(目标)只需要专注表演(核心功能);
  • 律师代理:律师(代理)处理法律流程(附加功能),当事人(目标)只需陈述事实(核心功能)。

1.3 代理模式的核心角色

代理模式的核心包含 4 个角色,所有代理实现都围绕这 4 个角色展开:

角色名称 核心职责
抽象主题(Subject) 定义目标对象和代理对象的共同接口 / 抽象类,确保代理对象可替代目标对象(里氏替换原则);
真实主题(RealSubject) 真正执行业务逻辑的目标对象,是代理的最终调用目标;
代理对象(Proxy) 实现 / 继承抽象主题,持有真实主题的引用,在调用目标方法前后添加附加逻辑;
客户端(Client) 仅与代理对象交互,不直接操作真实主题;

1.4 代理模式的核心价值

  • 解耦:将核心业务逻辑(如用户新增)与非核心逻辑(如日志、事务)分离,符合 “单一职责原则”;
  • 扩展:无需修改目标对象源码,通过代理即可新增功能(开放封闭原则);
  • 控制:可控制对目标对象的访问(如权限校验、限流、熔断);
  • 隐藏:可隐藏目标对象的实现细节(如 RPC 代理隐藏远程调用细节)。

二、静态代理:手动编写的 “专属代理”

静态代理是最基础的代理实现方式,代理类由开发者手动编写,在编译期就确定了代理类与目标类的绑定关系,属于 “一对一” 的专属代理。

2.1 实现步骤

  1. 定义抽象主题接口,声明核心业务方法;
  2. 实现真实主题类,完成核心业务逻辑;
  3. 编写代理类,实现抽象主题接口,持有真实主题引用;
  4. 在代理类的方法中,调用目标方法并添加附加逻辑;
  5. 客户端通过代理类调用业务方法。

2.2 实战案例:用户服务日志代理

以 “用户新增功能” 为例,通过静态代理添加日志记录功能。

步骤 1:定义抽象主题接口
/**
 * 抽象主题:用户服务接口(定义核心业务方法)
 */
public interface UserService {
    /**
     * 新增用户
     * @param username 用户名
     * @param age 年龄
     * @return 是否新增成功
     */
    boolean addUser(String username, int age);
}
步骤 2:实现真实主题类
/**
 * 真实主题:用户服务实现类(核心业务逻辑)
 */
public class UserServiceImpl implements UserService {
    @Override
    public boolean addUser(String username, int age) {
        // 核心业务逻辑:模拟数据库新增用户
        if (username == null || username.isEmpty()) {
            throw new IllegalArgumentException("用户名不能为空");
        }
        System.out.println("【核心逻辑】新增用户:" + username + ",年龄:" + age);
        return true;
    }
}
步骤 3:编写静态代理类
/**
 * 静态代理类:为UserService添加日志功能
 */
public class UserServiceStaticProxy implements UserService {
    // 持有真实主题引用
    private final UserService target;

    // 通过构造器注入目标对象
    public UserServiceStaticProxy(UserService target) {
        this.target = target;
    }

    @Override
    public boolean addUser(String username, int age) {
        // 1. 前置附加逻辑:日志记录(方法调用前)
        System.out.println("【静态代理-前置】开始调用addUser方法,参数:username=" + username + ", age=" + age);
        long startTime = System.currentTimeMillis();

        boolean result = false;
        try {
            // 2. 调用目标对象的核心方法
            result = target.addUser(username, age);
            // 3. 后置附加逻辑:日志记录(方法调用成功)
            System.out.println("【静态代理-后置】addUser方法调用成功,返回结果:" + result);
            return result;
        } catch (Exception e) {
            // 4. 异常附加逻辑:日志记录(方法调用异常)
            System.out.println("【静态代理-异常】addUser方法调用失败,异常信息:" + e.getMessage());
            throw e; // 抛出异常,不影响上层处理
        } finally {
            // 5. 收尾逻辑:性能监控
            long endTime = System.currentTimeMillis();
            System.out.println("【静态代理-耗时】addUser方法执行耗时:" + (endTime - startTime) + "ms");
        }
    }
}
步骤 4:客户端测试
/**
 * 客户端:通过静态代理调用目标方法
 */
public class StaticProxyClient {
    public static void main(String[] args) {
        // 1. 创建真实目标对象
        UserService target = new UserServiceImpl();
        // 2. 创建代理对象,注入目标对象
        UserService proxy = new UserServiceStaticProxy(target);
        
        // 3. 调用代理方法(正常场景)
        System.out.println("===== 正常场景 =====");
        proxy.addUser("张三", 25);
        
        // 4. 调用代理方法(异常场景)
        System.out.println("\n===== 异常场景 =====");
        try {
            proxy.addUser("", 20);
        } catch (IllegalArgumentException e) {
            System.out.println("客户端捕获异常:" + e.getMessage());
        }
    }
}
运行结果
===== 正常场景 =====
【静态代理-前置】开始调用addUser方法,参数:username=张三, age=25
【核心逻辑】新增用户:张三,年龄:25
【静态代理-后置】addUser方法调用成功,返回结果:true
【静态代理-耗时】addUser方法执行耗时:1ms

===== 异常场景 =====
【静态代理-前置】开始调用addUser方法,参数:username=, age=20
【静态代理-异常】addUser方法调用失败,异常信息:用户名不能为空
【静态代理-耗时】addUser方法执行耗时:0ms
客户端捕获异常:用户名不能为空

2.3 静态代理的优缺点

优点
  • 实现简单:纯原生 Java 实现,无需依赖任何框架,新手易理解;
  • 性能最优:编译期确定代理逻辑,无反射、无字节码生成开销;
  • 逻辑清晰:代理类与目标类一一对应,调试时可直接定位代码。
缺点
  • 代码冗余:每一个目标类都需要编写对应的代理类,若系统中有 100 个服务类,就需要 100 个代理类;
  • 维护成本高:若抽象主题接口新增 / 修改方法,所有代理类都需同步修改;
  • 扩展性差:代理逻辑无法复用,不同目标类的附加逻辑(如日志)需重复编写。

2.4 静态代理的适用场景

仅适用于目标类数量极少、业务逻辑固定、无需频繁扩展的简单场景,如小型工具类、固定流程的业务模块,实际企业开发中使用频率极低。

三、JDK 动态代理:基于接口的 “通用代理”

为解决静态代理的代码冗余问题,Java 提供了原生的动态代理机制 ——JDK 动态代理。代理类无需手动编写,而是在运行时通过反射动态生成,可代理所有实现了接口的目标类,实现 “一套代理逻辑适配所有目标类”。

3.1 核心原理

JDK 动态代理的核心依赖 java.lang.reflect 包下的两个类 / 接口:

  • Proxy:核心工具类,通过 newProxyInstance() 方法动态生成代理类的字节码,并创建代理对象;
  • InvocationHandler:调用处理器接口,所有代理方法的逻辑都会委托给该接口的 invoke() 方法处理。

其底层逻辑可概括为:

  1. 代理类由 Proxy 类动态生成,继承自 java.lang.reflect.Proxy,并实现目标类的所有接口;
  2. 代理类的所有接口方法都会调用 InvocationHandlerinvoke() 方法;
  3. invoke() 方法中,开发者可统一处理前置、后置、异常逻辑,并通过反射调用目标方法;
  4. 由于 Java 单继承限制(代理类已继承 Proxy),JDK 动态代理只能代理实现了接口的类

3.2 核心 API 详解

类 / 接口 核心方法 参数说明
Proxy newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) - loader:目标对象的类加载器;- interfaces:目标对象实现的所有接口;- h:调用处理器(核心逻辑)
InvocationHandler invoke(Object proxy, Method method, Object[] args) - proxy:生成的代理对象(一般不使用);- method:当前调用的目标方法;- args:目标方法的参数数组;返回值:目标方法的执行结果

3.3 实战案例:通用日志动态代理

实现一个通用的 JDK 动态代理工具,可给任意实现了接口的目标类添加日志和性能监控功能。

步骤 1:编写通用调用处理器
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 通用JDK动态代理调用处理器
 * 统一处理所有代理方法的日志、性能监控逻辑
 */
public class JdkLogInvocationHandler implements InvocationHandler {
    // 持有目标对象引用(通用类型,适配所有目标类)
    private final Object target;

    public JdkLogInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 1. 前置逻辑:日志记录(含时间戳)
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String methodName = method.getName();
        System.out.println("【JDK动态代理-" + sdf.format(new Date()) + "】开始调用方法:" + methodName);
        System.out.println("【JDK动态代理】方法参数:" + argsToString(args));
        
        long startTime = System.currentTimeMillis();
        Object result = null;

        try {
            // 2. 调用目标对象的核心方法(反射)
            result = method.invoke(target, args);
            // 3. 后置逻辑:调用成功日志
            System.out.println("【JDK动态代理-" + sdf.format(new Date()) + "】方法" + methodName + "调用成功,返回结果:" + result);
            return result;
        } catch (Exception e) {
            // 4. 异常逻辑:调用失败日志(解包原始异常)
            Throwable realException = e.getTargetException() == null ? e : e.getTargetException();
            System.out.println("【JDK动态代理-" + sdf.format(new Date()) + "】方法" + methodName + "调用失败,异常:" + realException.getMessage());
            throw realException; // 抛出原始异常,避免包装
        } finally {
            // 5. 收尾逻辑:性能监控
            long endTime = System.currentTimeMillis();
            System.out.println("【JDK动态代理】方法" + methodName + "执行耗时:" + (endTime - startTime) + "ms\n");
        }
    }

    /**
     * 参数数组转字符串,方便日志打印
     */
    private String argsToString(Object[] args) {
        if (args == null || args.length == 0) {
            return "无参数";
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < args.length; i++) {
            sb.append("arg").append(i + 1).append("=").append(args[i]);
            if (i < args.length - 1) {
                sb.append(", ");
            }
        }
        return sb.toString();
    }
}
步骤 2:编写 JDK 动态代理工具类
import java.lang.reflect.Proxy;

/**
 * JDK动态代理工具类
 * 提供通用的代理对象生成方法
 */
public class JdkProxyFactory {
    /**
     * 生成目标对象的代理对象
     * @param target 目标对象(必须实现至少一个接口)
     * @param <T> 目标对象类型
     * @return 代理对象
     */
    @SuppressWarnings("unchecked")
    public static <T> T createProxy(T target) {
        // 1. 获取目标对象的类加载器
        ClassLoader classLoader = target.getClass().getClassLoader();
        // 2. 获取目标对象实现的所有接口
        Class<?>[] interfaces = target.getClass().getInterfaces();
        // 3. 创建调用处理器
        JdkLogInvocationHandler handler = new JdkLogInvocationHandler(target);
        // 4. 动态生成代理对象并返回
        return (T) Proxy.newProxyInstance(classLoader, interfaces, handler);
    }
}
步骤 3:客户端测试(复用 UserService 体系)
/**
 * 客户端:测试JDK动态代理
 */
public class JdkProxyClient {
    public static void main(String[] args) {
        // 1. 创建目标对象(实现了接口)
        UserService target = new UserServiceImpl();
        // 2. 生成动态代理对象
        UserService proxy = JdkProxyFactory.createProxy(target);
        
        // 3. 调用代理方法(正常场景)
        System.out.println("===== 正常场景 =====");
        proxy.addUser("李四", 30);
        
        // 4. 新增测试:代理另一类方法(验证通用性)
        System.out.println("===== 多类适配 =====");
        OrderService orderTarget = new OrderServiceImpl();
        OrderService orderProxy = JdkProxyFactory.createProxy(orderTarget);
        orderProxy.createOrder("ORDER_001", 100.0);
    }

    // 新增订单服务接口(验证通用性)
    interface OrderService {
        boolean createOrder(String orderNo, double amount);
    }

    // 订单服务实现类
    static class OrderServiceImpl implements OrderService {
        @Override
        public boolean createOrder(String orderNo, double amount) {
            System.out.println("【核心逻辑】创建订单:" + orderNo + ",金额:" + amount);
            return true;
        }
    }
}
运行结果
===== 正常场景 =====
【JDK动态代理-2026-03-11 16:00:00】开始调用方法:addUser
【JDK动态代理】方法参数:arg1=李四, arg2=30
【核心逻辑】新增用户:李四,年龄:30
【JDK动态代理-2026-03-11 16:00:00】方法addUser调用成功,返回结果:true
【JDK动态代理】方法addUser执行耗时:1ms

===== 多类适配 =====
【JDK动态代理-2026-03-11 16:00:00】开始调用方法:createOrder
【JDK动态代理】方法参数:arg1=ORDER_001, arg2=100.0
【核心逻辑】创建订单:ORDER_001,金额:100.0
【JDK动态代理-2026-03-11 16:00:00】方法createOrder调用成功,返回结果:true
【JDK动态代理】方法createOrder执行耗时:0ms

3.4 JDK 动态代理的优缺点

优点
  • 通用性强:一套代理逻辑可适配所有实现接口的目标类,无代码冗余;
  • 扩展性好:新增目标类无需修改代理逻辑,只需传入目标对象即可;
  • 原生支持:基于 JDK 原生 API 实现,无需依赖第三方框架。
缺点
  • 接口限制:只能代理实现了接口的类,无法代理普通类(无接口);
  • 继承限制:代理类继承自 Proxy,无法代理 final 类;
  • 反射开销:目标方法调用基于反射实现,性能略低于静态代理(现代 JVM 优化后,该开销可忽略)。

3.5 JDK 动态代理的适用场景

是企业开发中最常用的代理方式,适用于目标类实现了接口的所有场景,如 Spring AOP 对接口型 Bean 的代理、MyBatis Mapper 接口代理、RPC 接口代理等。

四、CGLIB 动态代理:基于继承的 “无接口代理”

JDK 动态代理的核心限制是 “必须实现接口”,而在实际开发中,很多业务类并未实现接口(如普通 POJO、工具类)。CGLIB(Code Generation Library)作为第三方字节码生成库,通过继承目标类生成子类的方式实现代理,突破了接口限制。

4.1 核心原理

CGLIB 基于 ASM 字节码操作框架,其核心原理为:

  1. 在运行时动态生成目标类的子类作为代理类;
  2. 代理类重写目标类的所有 非final、非private 方法;
  3. 通过 MethodInterceptor(方法拦截器)拦截所有重写方法的调用;
  4. 在拦截器中处理附加逻辑,并调用目标类的原始方法。

核心特点:

  • 无需目标类实现接口,直接代理普通类;
  • 代理类继承目标类,因此无法代理 final 类(无法继承),也无法代理 final 方法(无法重写);
  • 方法调用通过字节码直接调用,性能优于 JDK 动态代理(Spring 5 后已优化,两者性能差异极小)。

4.2 核心依赖与 API

依赖引入(Maven)

CGLIB 非 JDK 原生库,需手动引入依赖(Spring Core 已内置 CGLIB,Spring 项目无需额外引入):

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>
核心 API 详解
类 / 接口 核心方法 作用
Enhancer setSuperclass(Class<?> superclass)setCallback(Callback callback)create() 核心增强类,用于生成代理类:- 设置目标类为父类;- 设置回调拦截器;- 生成代理对象
MethodInterceptor intercept(Object obj, Method method, Object[] args, MethodProxy proxy) 方法拦截器,处理所有代理方法逻辑:- obj:代理对象;- method:目标方法;- args:方法参数;- proxy:方法代理(高效调用父类方法)
MethodProxy invokeSuper(Object obj, Object[] args) 调用父类(目标类)的原始方法,性能优于反射 method.invoke()

4.3 实战案例:CGLIB 通用代理工具

实现一个通用的 CGLIB 代理工具,代理无接口的普通类。

步骤 1:编写 CGLIB 方法拦截器
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * CGLIB方法拦截器
 * 统一处理代理方法的日志、性能监控逻辑
 */
public class CglibLogInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // 1. 前置逻辑:日志记录
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String methodName = method.getName();
        System.out.println("【CGLIB动态代理-" + sdf.format(new Date()) + "】开始调用方法:" + methodName);
        System.out.println("【CGLIB动态代理】方法参数:" + argsToString(args));
        
        long startTime = System.currentTimeMillis();
        Object result = null;

        try {
            // 2. 调用目标类的原始方法(高效调用)
            result = proxy.invokeSuper(obj, args);
            // 3. 后置逻辑:调用成功日志
            System.out.println("【CGLIB动态代理-" + sdf.format(new Date()) + "】方法" + methodName + "调用成功,返回结果:" + result);
            return result;
        } catch (Exception e) {
            // 4. 异常逻辑:调用失败日志
            System.out.println("【CGLIB动态代理-" + sdf.format(new Date()) + "】方法" + methodName + "调用失败,异常:" + e.getMessage());
            throw e;
        } finally {
            // 5. 收尾逻辑:性能监控
            long endTime = System.currentTimeMillis();
            System.out.println("【CGLIB动态代理】方法" + methodName + "执行耗时:" + (endTime - startTime) + "ms\n");
        }
    }

    /**
     * 参数数组转字符串
     */
    private String argsToString(Object[] args) {
        if (args == null || args.length == 0) {
            return "无参数";
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < args.length; i++) {
            sb.append("arg").append(i + 1).append("=").append(args[i]);
            if (i < args.length - 1) {
                sb.append(", ");
            }
        }
        return sb.toString();
    }
}
步骤 2:编写 CGLIB 代理工厂
import net.sf.cglib.proxy.Enhancer;

/**
 * CGLIB动态代理工厂
 * 生成无接口类的代理对象
 */
public class CglibProxyFactory {
    /**
     * 生成代理对象
     * @param targetClass 目标类的Class对象
     * @param <T> 目标类类型
     * @return 代理对象
     */
    @SuppressWarnings("unchecked")
    public static <T> T createProxy(Class<T> targetClass) {
        // 1. 创建增强器
        Enhancer enhancer = new Enhancer();
        // 2. 设置父类(目标类)
        enhancer.setSuperclass(targetClass);
        // 3. 设置方法拦截器
        enhancer.setCallback(new CglibLogInterceptor());
        // 4. 生成并返回代理对象
        return (T) enhancer.create();
    }
}
步骤 3:客户端测试(代理无接口类)
/**
 * 客户端:测试CGLIB动态代理
 */
public class CglibProxyClient {
    public static void main(String[] args) {
        // 1. 代理无接口的普通类
        System.out.println("===== 代理无接口类 =====");
        PayService payProxy = CglibProxyFactory.createProxy(PayService.class);
        payProxy.pay("USER_001", 200.5);
        
        // 2. 测试final方法(无法代理)
        System.out.println("===== 测试final方法 =====");
        payProxy.finalMethod();
    }

    /**
     * 无接口的普通类(支付服务)
     */
    static class PayService {
        // 普通方法(可被代理)
        public boolean pay(String userId, double amount) {
            System.out.println("【核心逻辑】用户" + userId + "支付金额:" + amount);
            return true;
        }

        // final方法(无法被代理)
        public final void finalMethod() {
            System.out.println("【核心逻辑】这是final方法,无法被CGLIB代理增强");
        }
    }
}
运行结果

plaintext

===== 代理无接口类 =====
【CGLIB动态代理-2026-03-11 16:30:00】开始调用方法:pay
【CGLIB动态代理】方法参数:arg1=USER_001, arg2=200.5
【核心逻辑】用户USER_001支付金额:200.5
【CGLIB动态代理-2026-03-11 16:30:00】方法pay调用成功,返回结果:true
【CGLIB动态代理】方法pay执行耗时:1ms

===== 测试final方法 =====
【核心逻辑】这是final方法,无法被CGLIB代理增强

4.4 CGLIB 动态代理的优缺点

优点
  • 无接口限制:可代理任意非 final 普通类,弥补 JDK 动态代理的不足;
  • 性能更优:通过字节码直接调用方法,性能略优于 JDK 动态代理;
  • 功能丰富:支持方法拦截、构造器拦截、回调过滤等高级功能。
缺点
  • 依赖第三方库:需引入 CGLIB/ASM 依赖(Spring 项目可忽略);
  • 继承限制:无法代理 final 类和 final 方法;
  • 初始化开销:动态生成字节码的初始化开销略高于 JDK 动态代理(运行时可忽略)。

4.5 CGLIB 动态代理的适用场景

适用于目标类未实现接口的场景,如 Spring AOP 对非接口型 Bean 的代理、MyBatis 延迟加载、Hibernate 实体代理等。

五、三种代理模式的核心对比(面试必背)

特性 静态代理 JDK 动态代理 CGLIB 动态代理
实现方式 手动编写代理类 反射 + 接口 字节码生成 + 继承
是否需要接口
代理类生成时机 编译期 运行时 运行时
核心限制 无(但代码冗余) 只能代理接口类 不能代理 final 类 / 方法
性能 最优(无额外开销) 中等(反射开销) 高(字节码直接调用)
代码冗余度 极高(一对一) 极低(通用代理) 极低(通用代理)
维护成本 高(接口修改需同步改) 低(通用逻辑) 低(通用逻辑)
Spring 默认使用 不使用 有接口时优先使用 无接口时使用

六、代理模式与 AOP 的关系

6.1 AOP 的核心本质

AOP(面向切面编程)的核心是 “横切逻辑”:将日志、事务、权限等与核心业务无关的逻辑(横切逻辑)从业务代码中抽离,通过 “切面” 统一管理。而动态代理是 AOP 实现的底层技术

6.2 Spring AOP 的代理策略

Spring AOP 自动选择代理方式:

  1. 若目标 Bean 实现了接口,默认使用 JDK 动态代理
  2. 若目标 Bean 未实现接口,使用 CGLIB 代理
  3. 可通过 proxy-target-class=true 强制使用 CGLIB 代理。

6.3 示例:Spring AOP 底层代理逻辑

// Spring AOP 核心拦截器(简化版)
public class AopAdviceInterceptor implements MethodInterceptor {
    private final Advice advice; // 切面逻辑(如@Before、@After)
    private final TargetSource targetSource; // 目标对象

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // 1. 执行前置通知(@Before)
        advice.before(method, args);
        try {
            // 2. 调用目标方法
            Object result = targetSource.getTarget().getClass().getMethod(method.getName(), method.getParameterTypes()).invoke(targetSource.getTarget(), args);
            // 3. 执行后置通知(@AfterReturning)
            advice.afterReturning(result);
            return result;
        } catch (Exception e) {
            // 4. 执行异常通知(@AfterThrowing)
            advice.afterThrowing(e);
            throw e;
        } finally {
            // 5. 执行最终通知(@After)
            advice.after();
        }
    }
}

七、总结

  1. 代理模式的核心:通过代理对象封装目标对象,实现核心逻辑与附加逻辑的解耦,核心是 “增强不修改”;
  2. 静态代理:简单但冗余,仅适用于简单固定场景;
  3. JDK 动态代理:基于接口,原生支持,是接口型 Bean 的首选;
  4. CGLIB 动态代理:基于继承,突破接口限制,适配无接口类;
  5. 动态代理是 AOP 的底层:Spring AOP、事务、日志等功能均依赖动态代理实现。

掌握 Java 代理的实现原理,不仅能理解设计模式的实战价值,更能打通 Spring 框架的底层逻辑,是 Java 后端开发者的核心基本功。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。