Java中的动态代理机制详解
字数 958 2025-11-03 20:46:32

Java中的动态代理机制详解

一、动态代理的概念与作用
动态代理是一种在运行时动态创建代理类和对象的技术,它允许你在不修改原始类代码的情况下,为对象的方法调用添加额外功能(如日志记录、权限检查、事务管理等)。动态代理的核心价值在于实现"横切关注点"的分离。

二、动态代理的实现方式
Java提供了两种主要的动态代理实现方式:

  1. JDK动态代理

    • 基于接口实现,要求目标类必须实现至少一个接口
    • 核心类:java.lang.reflect.Proxyjava.lang.reflect.InvocationHandler
  2. CGLIB动态代理

    • 基于继承实现,通过生成目标类的子类来创建代理
    • 可以代理没有实现接口的普通类

三、JDK动态代理的详细实现步骤

步骤1:定义业务接口

// 用户服务接口
public interface UserService {
    void addUser(String username);
    void deleteUser(String username);
}

步骤2:实现业务接口(目标类)

// 目标类 - 实际业务逻辑的实现
public class UserServiceImpl implements UserService {
    @Override
    public void addUser(String username) {
        System.out.println("添加用户: " + username);
    }
    
    @Override
    public void deleteUser(String username) {
        System.out.println("删除用户: " + username);
    }
}

步骤3:实现InvocationHandler接口

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class LoggingHandler implements InvocationHandler {
    private final Object target;  // 目标对象
    
    public LoggingHandler(Object target) {
        this.target = target;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 前置增强:方法执行前的逻辑
        System.out.println("【日志】开始执行方法: " + method.getName());
        System.out.println("【日志】参数: " + (args != null ? String.join(",", args) : "无"));
        
        long startTime = System.currentTimeMillis();
        
        // 调用目标对象的原始方法
        Object result = method.invoke(target, args);
        
        // 后置增强:方法执行后的逻辑
        long endTime = System.currentTimeMillis();
        System.out.println("【日志】方法执行耗时: " + (endTime - startTime) + "ms");
        System.out.println("【日志】方法执行完成");
        
        return result;
    }
}

步骤4:创建代理对象并使用

import java.lang.reflect.Proxy;

public class DynamicProxyDemo {
    public static void main(String[] args) {
        // 创建目标对象
        UserService target = new UserServiceImpl();
        
        // 创建InvocationHandler实例
        InvocationHandler handler = new LoggingHandler(target);
        
        // 创建代理对象
        UserService proxy = (UserService) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),  // 类加载器
            target.getClass().getInterfaces(),   // 接口数组
            handler                              // 调用处理器
        );
        
        // 通过代理对象调用方法
        proxy.addUser("张三");
        proxy.deleteUser("李四");
    }
}

四、CGLIB动态代理的实现

步骤1:添加CGLIB依赖

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

步骤2:实现MethodInterceptor接口

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class CglibLoggingInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("【CGLIB日志】开始执行方法: " + method.getName());
        
        long startTime = System.currentTimeMillis();
        // 调用父类(目标类)的方法
        Object result = proxy.invokeSuper(obj, args);
        
        long endTime = System.currentTimeMillis();
        System.out.println("【CGLIB日志】方法执行耗时: " + (endTime - startTime) + "ms");
        
        return result;
    }
}

步骤3:创建代理对象

import net.sf.cglib.proxy.Enhancer;

public class CglibProxyDemo {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        // 设置父类(目标类)
        enhancer.setSuperclass(UserServiceImpl.class);
        // 设置回调处理器
        enhancer.setCallback(new CglibLoggingInterceptor());
        
        // 创建代理对象
        UserService proxy = (UserService) enhancer.create();
        
        proxy.addUser("王五");
    }
}

五、两种动态代理的对比分析

特性 JDK动态代理 CGLIB动态代理
实现基础 基于接口 基于继承
性能 调用反射方法,较慢 直接调用父类方法,较快
限制 必须实现接口 不能代理final类和方法
依赖 JDK原生支持 需要额外jar包

六、动态代理的实际应用场景

  1. Spring AOP:Spring框架使用动态代理实现面向切面编程
  2. MyBatis:Mapper接口的代理实现
  3. Hibernate:延迟加载功能的实现
  4. RPC框架:远程方法调用的客户端代理
  5. 事务管理:声明式事务的实现基础

七、核心原理深入理解

动态代理的核心在于:

  • 代理类生成:在运行时通过字节码技术动态生成代理类的字节码
  • 方法转发:所有方法调用都被重定向到InvocationHandler的invoke方法
  • 责任链模式:通过代理链实现多个增强功能的组合

通过动态代理,我们可以实现业务逻辑与横切关注点的彻底分离,大大提高代码的可维护性和复用性。

Java中的动态代理机制详解 一、动态代理的概念与作用 动态代理是一种在运行时动态创建代理类和对象的技术,它允许你在不修改原始类代码的情况下,为对象的方法调用添加额外功能(如日志记录、权限检查、事务管理等)。动态代理的核心价值在于实现"横切关注点"的分离。 二、动态代理的实现方式 Java提供了两种主要的动态代理实现方式: JDK动态代理 基于接口实现,要求目标类必须实现至少一个接口 核心类: java.lang.reflect.Proxy 和 java.lang.reflect.InvocationHandler CGLIB动态代理 基于继承实现,通过生成目标类的子类来创建代理 可以代理没有实现接口的普通类 三、JDK动态代理的详细实现步骤 步骤1:定义业务接口 步骤2:实现业务接口(目标类) 步骤3:实现InvocationHandler接口 步骤4:创建代理对象并使用 四、CGLIB动态代理的实现 步骤1:添加CGLIB依赖 步骤2:实现MethodInterceptor接口 步骤3:创建代理对象 五、两种动态代理的对比分析 | 特性 | JDK动态代理 | CGLIB动态代理 | |------|-------------|---------------| | 实现基础 | 基于接口 | 基于继承 | | 性能 | 调用反射方法,较慢 | 直接调用父类方法,较快 | | 限制 | 必须实现接口 | 不能代理final类和方法 | | 依赖 | JDK原生支持 | 需要额外jar包 | 六、动态代理的实际应用场景 Spring AOP :Spring框架使用动态代理实现面向切面编程 MyBatis :Mapper接口的代理实现 Hibernate :延迟加载功能的实现 RPC框架 :远程方法调用的客户端代理 事务管理 :声明式事务的实现基础 七、核心原理深入理解 动态代理的核心在于: 代理类生成 :在运行时通过字节码技术动态生成代理类的字节码 方法转发 :所有方法调用都被重定向到InvocationHandler的invoke方法 责任链模式 :通过代理链实现多个增强功能的组合 通过动态代理,我们可以实现业务逻辑与横切关注点的彻底分离,大大提高代码的可维护性和复用性。