普通代理
- 定义一个接口
public interface HelloInterface {
void sayHello();
}
- 定义一个被代理类
public class Hello implements HelloInterface{
@Override
public void sayHello() {
System.out.println("Hello zhanghao!");
}
}
如果我们单纯的使用普通代理,只需要将被代理类作为代理类的一个属性,然后代理类实现接口方法的时候调用被代理类的同名方法即可.
public class HelloProxy implements HelloInterface{
private HelloInterface helloInterface = new Hello();
@Override
public void sayHello() {
System.out.println("Before invoke sayHello" );
helloInterface.sayHello();
System.out.println("After invoke sayHello");
}
}
动态代理代理对象—可以使用同一个代理类代理任意被代理类
public class ProxyHandler implements InvocationHandler{
private Object object;
public ProxyHandler(Object object){
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before invoke " + method.getName());
method.invoke(object, args);
System.out.println("After invoke " + method.getName());
return null;
}
}
public static void main(String[] args) {
System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
HelloInterface hello = new Hello();
InvocationHandler handler = new ProxyHandler(hello);
HelloInterface proxyHello = (HelloInterface) Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), handler);
proxyHello.sayHello();
}
输出:
Before invoke sayHello
Hello zhanghao!
After invoke sayHello
动态代理代理接口—即便没有任何类的实例,也能使用动态代理(也能代理接口)
- 定义一个接口
public interface Protocol {
public int add(int a, int b);
}
- 定义一个handle
class DyProxy implements InvocationHandler {
Object object;
DyProxy() {
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
System.out.println(method.getName());
System.out.println(args);
return null;
}
}
- 使用接口方法
public static void main(String[] args) throws IOException {
Protocol proxyClass = (Protocol) Proxy.newProxyInstance(Protocol.class.getClassLoader(), new Class[]{Protocol.class}, new DyProxy());
System.out.println(proxyClass.add(1, 2));
}
自我实现RPC
只需要在动态代理代理接口的时候,在invoke函数里实现一个RPC通信即可
- 协议
public interface Protocol {
public int add(int a, int b);
public int sub(int a, int b);
}
- 服务器
package blm.myRPC;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @ProjectName: hadoop_learn
* @Package: blm.myRPC
* @ClassName: Server
* @Author: chenmengqi
* @Description:
* @Date: 2020/2/28 10:25 下午
* @Version: 1.0
*/
public class Server implements Protocol {
@Override
public int add(int a, int b) {
return a + b;
}
public int sub(int a, int b) {
return a - b;
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
ServerSocket serverSocket = new ServerSocket(8006);
Server server = new Server();
while (true) {
Socket accept = serverSocket.accept();
ObjectInputStream objectInputStream = new ObjectInputStream(accept.getInputStream());
Message message = (Message) objectInputStream.readObject();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(accept.getOutputStream());
System.out.println(message.getMethod());
if ("add".equals(message.getMethod())) {
message.setRes(server.add(message.getArg1(), message.getArg2()));
} else if ("sub".equals(message.getMethod())) {
message.setRes(server.sub(message.getArg1(), message.getArg2()));
}
System.out.println(message);
objectOutputStream.writeObject(message);
}
}
}
- 客户端
public class Client {
public static void main(String[] args) throws IOException {
Protocol proxyClass = (Protocol) Proxy.newProxyInstance(Protocol.class.getClassLoader(), new Class[]{Protocol.class}, new DyProxy());
System.out.println(proxyClass.add(2, 1));
System.out.println(proxyClass.sub(2, 1));
}
}
class DyProxy implements InvocationHandler {
Socket socket;
DyProxy() throws IOException {
this.socket = new Socket("127.0.0.1", 8006);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Message message = new Message();
message.setMethod(method.getName());
message.setArg1((int) args[0]);
message.setArg2((int) args[1]);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(this.socket.getOutputStream());
objectOutputStream.writeObject(message);
// objectOutputStream.flush();
// socket.shutdownOutput();
ObjectInputStream objectInputStream = new ObjectInputStream(this.socket.getInputStream());
message = (Message) objectInputStream.readObject();
// socket.shutdownOutput();
return message.getRes();
}
}