从静态代理到动态代理的演进
在Java开发中,当我们需要为某个对象添加额外功能(如日志、权限校验)时,静态代理是最直接的实现方式——编写一个代理类,实现与目标对象相同的接口,在方法中调用目标对象的方法并添加额外逻辑,但这种方式存在明显缺陷:每个目标对象都需要一个代理类,当接口方法变更时,代理类也需要同步修改,导致代码维护成本激增,动态代理的出现,完美解决了这一痛点。

动态代理的核心原理
动态代理的核心是JDK提供的Proxy类和InvocationHandler接口。Proxy类是动态代理的“工厂”,通过newProxyInstance方法可以在运行时动态生成代理类;InvocationHandler则是代理对象的“处理器”,定义了当代理方法被调用时的具体行为,当外部代码调用代理对象的方法时,JVM会自动将调用转发给InvocationHandler的invoke方法,并传入方法名、参数类型、参数值等信息,由invoke方法决定如何处理——可以直接调用目标对象的方法,也可以添加额外逻辑(如日志记录),甚至可以拒绝调用。
动手实现:动态代理的步骤
以日志记录场景为例,假设有一个UserService接口,包含addUser方法,首先定义UserService接口和其实现类UserServiceImpl;然后创建LogInvocationHandler实现InvocationHandler接口,在invoke方法中添加日志逻辑,并调用目标对象的方法;最后通过Proxy.newProxyInstance生成代理实例,代码示例如下(简化):

UserService proxy = (UserService) Proxy.newProxyInstance(
UserService.class.getClassLoader(),
new Class[]{UserService.class},
new LogInvocationHandler(new UserServiceImpl())
);
调用proxy.addUser("张三")时,会先执行日志记录,再调用UserServiceImpl.addUser。
动态代理的典型应用场景

- AOP(面向切面编程):Spring AOP利用动态代理将横切逻辑(如事务、异常处理)从业务逻辑中分离,实现“无侵入”增强;
- 日志与监控:通过
InvocationHandler统一记录方法调用日志、执行时间等,避免在业务代码中硬编码; - 权限校验:在
invoke方法中检查调用者权限,未授权则抛出异常; - RPC框架:客户端通过动态代理生成远程服务接口的代理对象,调用方法时自动转换为网络请求,屏蔽底层通信细节。
小编总结与延伸
动态代理通过运行时生成代理类,彻底消除了静态代理的代码冗余问题,是Java中实现“非侵入式”功能增强的核心技术,需要注意的是,JDK动态代理要求目标对象必须实现接口,若没有接口,可使用CGLIB等字节码增强库,理解动态代理的原理,不仅能提升对Java反射机制的认识,更能为掌握Spring等框架的底层设计打下基础。









