深度解析动态代理的运作机制核心原理:
- 反射基础:动态代理依赖Java反射机制,在运行时分析类信息、调用方法。
- InvocationHandler接口:开发者实现此接口,在invoke(Object proxy, Method method, Object[] args)中编写代理逻辑(如前置/后置处理)。
- 动态类生成:Proxy.newProxyInstance(ClassLoader, Class<?>[], InvocationHandler)在内存中动态创建实现指定接口的代理类并实例化。该代理类将方法调用委托给InvocationHandler。
关键优势
· 解耦:核心业务逻辑与通用功能(日志、安全等)分离。
· 灵活扩展:无需修改源码即可为类添加新行为,符合开闭原则。
· 代码复用:同一代理逻辑可应用于多个接口或类。
典型应用场景
· AOP编程(如Spring AOP)
· 远程方法调用(RPC)
· 声明式事务管理
· 性能监控、日志记录
· 访问控制
局限与注意
· 仅支持接口代理:无法代理具体类(需使用CGLIB等库)。
· 性能开销:反射调用比直接调用慢,高频场景需评估。
· 复杂性:过度使用可能导致调试困难。
实战示例:动态代理实现日志增强
import java.lang.reflect.*;
// 1. 定义业务接口
interface UserService {
void addUser(String name);
void deleteUser(int id);
}
// 2. 真实实现类
class UserServiceImpl implements UserService {
public void addUser(String name) {
System.out.println("添加用户: " + name);
}
public void deleteUser(int id) {
System.out.println("删除用户ID: " + id);
}
}
// 3. 调用处理器(实现代理逻辑)
class LoggingHandler implements InvocationHandler {
private 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());
Object result = method.invoke(target, args); // 调用真实对象的方法
System.out.println("[日志] 执行完成: " + method.getName());
return result;
}
}
// 4. 客户端使用动态代理
public class DynamicProxyDemo {
public static void main(String[] args) {
UserService realService = new UserServiceImpl();
// 动态创建代理对象
UserService proxy = (UserService) Proxy.newProxyInstance(
realService.getClass().getClassLoader(),
realService.getClass().getInterfaces(),
new LoggingHandler(realService) // 传入处理器
);
// 通过代理对象调用方法(自动触发日志增强)
proxy.addUser("张三");
proxy.deleteUser(1001);
}
}
输出结果:
[日志] 开始执行: addUser
添加用户: 张三
[日志] 执行完成: addUser
[日志] 开始执行: deleteUser
删除用户ID: 1001
[日志] 执行完成: deleteUser
核心价值
Java动态代理通过运行时动态生成代理类,结合InvocationHandler的灵活拦截能力,实现了非侵入式的功能增强。它不仅是理解Spring等框架AOP实现的关键,更是设计高扩展性、低耦合系统的利器。掌握它,你将在复杂系统设计中拥有更强的“代码易容术”。
264

被折叠的 条评论
为什么被折叠?



