以下是Java动态代理的逐步解释:
java.lang.reflect.Proxy
:生成代理对象的工具类。java.lang.reflect.InvocationHandler
:代理对象的方法调用处理器接口。步骤1:自定义接口java
代码解读复制代码public interface UserService {
void addUser(String username);
void deleteUser(String username);
}
步骤2:实现自定接口java
代码解读复制代码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:实现InvocationHandlerjava
代码解读复制代码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());
// 执行目标方法
Object result = method.invoke(target, args);
// 方法执行后逻辑
System.out.println("调用方法后: " + method.getName());
return result;
}
}
步骤4:生成代理对象java
代码解读复制代码import java.lang.reflect.Proxy;
public class DynamicProxyDemo {
public static void main(String[] args) {
// 创建目标对象
UserService realService = new UserServiceImpl();
// 创建InvocationHandler实例
InvocationHandler handler = new LoggingHandler(realService);
// 生成代理对象
UserService proxyService = (UserService) Proxy.newProxyInstance(
UserService.class.getClassLoader(), // 类加载器
new Class[]{UserService.class}, // 代理的接口数组
handler // InvocationHandler实例
);
// 通过代理对象调用方法
proxyService.addUser("Alice");
proxyService.deleteUser("Bob");
}
}
代码解读复制代码调用方法前: addUser
添加用户: Alice
调用方法后: addUser
调用方法前: deleteUser
删除用户: Bob
调用方法后: deleteUser
Proxy.newProxyInstance()
在运行时动态生成代理类字节码。Proxy
并实现指定接口。addUser()
)。InvocationHandler.invoke()
。invoke()
方法执行前置逻辑 → 调用目标方法 → 执行后置逻辑。限制 | 说明 | 解决方案 |
---|---|---|
只能代理接口 | 无法直接代理没有接口的类 | 使用CGLIB库(如Spring AOP默认行为) |
性能开销 | 反射调用比直接调用慢约5-20倍 | 对性能敏感场景使用AspectJ编译时织入 |
无法代理final方法 | final方法无法被重写 | 避免代理final方法或使用CGLIB |
特性 | JDK动态代理 | CGLIB |
---|---|---|
代理方式 | 基于接口 | 基于类继承 |
性能 | 较慢(反射调用) | 较快(方法调用无反射) |
依赖 | 无需第三方库 | 需要引入CGLIB库 |
方法限制 | 无法代理无接口的类 | 无法代理final方法或类 |
查看生成的代理类字节码java
代码解读复制代码// 在启动JVM时添加以下参数
System.setProperty("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");
处理Object方法(如toString)java
代码解读复制代码@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass() == Object.class) {
// 直接调用Object方法,不进行代理增强
return method.invoke(target, args);
}
// 其他方法的代理逻辑
// ...
}
动态代理实现RPC框架伪代码java
代码解读复制代码public class RpcProxy implements InvocationHandler {
private final String host;
private final int port;
public RpcProxy(String host, int port) {
this.host = host;
this.port = port;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
// 1. 序列化请求参数
byte[] requestData = serialize(method, args);
// 2. 发送网络请求
byte[] responseData = sendRequest(host, port, requestData);
// 3. 反序列化响应结果
return deserialize(responseData, method.getReturnType());
}
}