Java 动态代理在远程过程调用(RPC)中非常有用,可以隐藏网络通信的复杂性,使得远程调用看起来像是本地方法调用。
场景说明
假设我们有一个简单的服务接口 CalculatorService
,它提供了加法和减法的功能。我们希望客户端可以通过动态代理的方式调用这个服务接口,实际上这些调用会通过网络发送到远程的服务端进行计算。
1. 定义服务接口
首先定义一个服务接口 CalculatorService
:
// 服务接口
public interface CalculatorService {
int add(int a, int b);
int subtract(int a, int b);
}
2. 实现服务端
服务端实现了 CalculatorService
接口,并在远程提供服务:
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
// 服务端实现类
public class CalculatorServiceImpl implements CalculatorService {
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public int subtract(int a, int b) {
return a - b;
}
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("服务端启动,等待连接...");
while (true) {
Socket clientSocket = serverSocket.accept();
ObjectInputStream input = new ObjectInputStream(clientSocket.getInputStream());
String methodName = input.readUTF();
int a = input.readInt();
int b = input.readInt();
ObjectOutputStream output = new ObjectOutputStream(clientSocket.getOutputStream());
CalculatorService service = new CalculatorServiceImpl();
if (methodName.equals("add")) {
output.writeInt(service.add(a, b));
} else if (methodName.equals("subtract")) {
output.writeInt(service.subtract(a, b));
}
output.flush();
clientSocket.close();
}
}
}
3. 实现客户端动态代理
客户端使用动态代理调用远程服务:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
// 动态代理处理器
public class RpcInvocationHandler implements InvocationHandler {
private String host;
private int port;
public RpcInvocationHandler(String host, int port) {
this.host = host;
this.port = port;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Socket socket = new Socket(host, port);
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
output.writeUTF(method.getName());
for (Object arg : args) {
output.writeObject(arg);
}
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
Object result = input.readObject();
input.close();
output.close();
socket.close();
return result;
}
}
// 客户端代码
public class RpcClient {
@SuppressWarnings("unchecked")
public static <T> T getProxy(Class<T> serviceClass, String host, int port) {
return (T) Proxy.newProxyInstance(serviceClass.getClassLoader(), new Class<?>[]{serviceClass}, new RpcInvocationHandler(host, port));
}
public static void main(String[] args) {
CalculatorService service = RpcClient.getProxy(CalculatorService.class, "localhost", 8080);
int result1 = service.add(10, 5);
int result2 = service.subtract(10, 5);
System.out.println("加法结果: " + result1);
System.out.println("减法结果: " + result2);
}
}
4. 运行说明
- 服务端:运行
CalculatorServiceImpl
,它将开启一个 TCP 服务器,在 8080 端口等待客户端请求。 - 客户端:运行
RpcClient
,通过动态代理获得CalculatorService
的代理对象,并调用add
和subtract
方法。这些方法调用将通过网络发送到服务端,由服务端处理并返回结果。
5. 执行结果
运行客户端后,输出如下:
加法结果: 15
减法结果: 5
6. 解析
- 服务端:简单实现了一个 TCP 服务器,通过
ObjectInputStream
和ObjectOutputStream
来接收和发送请求。 - 客户端:使用 JDK 动态代理,通过
RpcInvocationHandler
拦截方法调用,将方法名和参数序列化后发送给服务端,再从服务端获取结果。
评论 (0)