Java动态代理的实现原理与代码示例
Java动态代理是一种在运行时动态生成代理类并增强目标对象方法的技术,它无需手动编写代理类,而是通过反射机制动态创建代理对象,这种机制在AOP(面向切面编程)、日志记录、事务管理等领域有广泛应用,本文将详细介绍Java动态代理的实现方式、核心组件及代码示例。

动态代理的核心组件
Java动态代理主要涉及两个核心组件:InvocationHandler接口和Proxy类。
-
InvocationHandler接口
该接口定义了代理对象的调用处理器,其核心方法是invoke(Object proxy, Method method, Object[] args),当代理对象的方法被调用时,JVM会自动将调用转发到InvocationHandler的invoke方法中。proxy:代理对象本身。method:被调用的方法对象。args:方法调用时的参数数组。
-
Proxy类
该类是Java动态代理的工厂,提供了静态方法newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)用于创建代理实例。loader:类加载器,通常使用目标类的类加载器。interfaces:目标类实现的接口数组,代理对象会实现这些接口。h:调用处理器,即实现了InvocationHandler接口的对象。
动态代理的实现步骤
实现动态代理的步骤如下:

-
定义目标接口和实现类
首先需要定义一个接口及其实现类,代理对象将基于该接口生成。public interface UserService { void addUser(String name); String getUserInfo(int id); } public class UserServiceImpl implements UserService { @Override public void addUser(String name) { System.out.println("Add user: " + name); } @Override public String getUserInfo(int id) { return "User info: " + id; } } -
实现InvocationHandler接口
创建一个调用处理器,在invoke方法中添加增强逻辑(如日志记录、权限校验等)。import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class LogHandler implements InvocationHandler { private Object target; // 目标对象 public LogHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 前置增强:日志记录 System.out.println("Before method: " + method.getName()); // 调用目标方法 Object result = method.invoke(target, args); // 后置增强:日志记录 System.out.println("After method: " + method.getName()); return result; } } -
创建代理对象并调用方法
使用Proxy.newProxyInstance方法生成代理对象,并通过代理对象调用目标方法。public class DynamicProxyDemo { public static void main(String[] args) { // 创建目标对象 UserService userService = new UserServiceImpl(); // 创建调用处理器 InvocationHandler handler = new LogHandler(userService); // 创建代理对象 UserService proxy = (UserService) Proxy.newProxyInstance( userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), handler ); // 通过代理对象调用方法 proxy.addUser("Alice"); System.out.println(proxy.getUserInfo(1)); } }
动态代理的执行流程
- 当调用
proxy.addUser("Alice")时,JVM会检测到proxy是动态生成的代理对象,因此不会直接执行UserServiceImpl的addUser方法。 - 转而调用
LogHandler的invoke方法,传入method(addUser方法对象)、args(参数数组)等。 - 在
invoke方法中,先执行前置增强(打印日志),然后通过method.invoke(target, args)调用目标方法,最后执行后置增强。
动态代理的局限性
-
只能基于接口代理
Java动态代理要求目标类必须实现接口,因为代理对象会实现这些接口,如果目标类是普通类(未实现接口),则无法使用动态代理。
-
性能开销
动态代理通过反射调用方法,相比直接调用会有一定的性能损耗,在性能敏感的场景中,可以考虑使用CGLIB等第三方库。
Java动态代理通过InvocationHandler和Proxy类实现了灵活的方法增强机制,适用于需要解耦和动态扩展的场景,掌握其实现原理和代码编写方式,有助于在实际开发中更好地应用AOP等高级特性。



















