reflex
Reflection is one of the characteristics of Java programming language. It allows running Java programs to check themselves, or "self audit", and can directly operate the internal properties and methods of the program.
Some classes of reflection
Field class: represents the object properties obtained in reflection
Constructor class: represents the constructor of the class obtained in reflection
Method class: represents the method of the class obtained in reflection
Class: class object
Usage example of reflection
student class
@Data @AllArgsConstructor @NoArgsConstructor public class Student { private String name; private int age; }
Reflection test class
public class ReflectionTest { @Test public void test1() throws Exception{ Student c = new Student("Zhang San", 22); final Class<?> clazz = Class.forName("com.Student"); //Get the public property of the class. If the property is not public, it cannot be obtained final Field[] fields = clazz.getFields(); for (Field field : fields) { System.out.println(field.getName()); } System.out.println("----------------------All properties----------------------"); //Get all the properties of the class, including the properties decorated with private final Field[] declaredFields = clazz.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println(declaredField.getName()); } System.out.println("----------------------All methods----------------------"); //Get all the methods of the class, including the methods decorated with private final Method[] declaredMethods = clazz.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println(declaredMethod.getName()); } System.out.println("----------------------Gets the specific value of the object property----------------------"); final Field age = clazz.getDeclaredField("age"); //When this property is set to true, you can operate on the properties of the object age.setAccessible(true); System.out.println(c); age.set(c,1111); System.out.println(c); System.out.println(age.get(c)); //Construct objects by construction method final Object o = clazz.newInstance(); System.out.println(o); //Get construction method final Constructor<?>[] constructors = clazz.getConstructors(); for (Constructor<?> constructor : constructors) { System.out.println(constructor.toString()); } } }
jdk dynamic agent
proxy pattern
Definition of proxy pattern in head first design pattern: proxy pattern provides a substitute or placeholder for another object to control access to this object.
Static proxy
//Rental interface public interface RentAble { void rent(); }
//Landlord class public class Landlord implements RentAble{ @Override public void rent() { System.out.println("Rental housing!!!"); } }
//Intermediary class public class Intermediary implements RentAble{ private RentAble rentAble; public Intermediary(RentAble rentAble) { this.rentAble = rentAble; } @Override public void rent() { System.out.println("Show people the house!!!"); rentAble.rent(); } }
In this example, when we call the interface, we only need to call the rental method of the intermediary class to complete the rental, which is also called static proxy.
Dynamic agent
In fact, dynamic proxy is to dynamically generate the mediation class in the above example by the jvm according to reflection and other mechanisms when the program is running. The relationship between proxy class and delegate class is determined only when the program is running.
public static void main(String[] args) { RentAble landlord=new Landlord(); RentAble rentAble = (RentAble) Proxy.newProxyInstance(Landlord.class.getClassLoader(), new Class[]{RentAble.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Show people the house!!!"); Object invoke = method.invoke(landlord,args); return invoke; } }); rentAble.rent(); }
RPC
RPC (Remote Procedure Call) Remote Procedure Call protocol
In fact, rpc is also implemented based on dynamic agent. We can send the interface, method name, method parameters and other information we need to call to another computer through the network. The other computer calls its local method according to the information we send, and then transmits the returned parameters to us.
Code required by the client
Client get proxy object
public class Stub { /** * Get proxy object * @param clazz Interface to get * @return */ public static Object getService(Class clazz) { InvocationHandler h = new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //Connect to remote server Socket socket = new Socket("127.0.0.1", 4396); ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream()); //Send interface name, method name, method parameter type and method parameter list to remote objectOutputStream.writeUTF(clazz.getName()); objectOutputStream.writeUTF(method.getName()); objectOutputStream.writeObject(method.getParameterTypes()); objectOutputStream.writeObject(args); //Receive return value ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream()); Object o = objectInputStream.readObject(); //Close flow objectOutputStream.close(); socket.close(); return o; } }; return Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, h); } }
The interface that the client needs to call
public interface Service { /** * Get student object * @param id Student id * @return */ Student queryStudentById(long id); }
Entity class
public class Student implements Serializable { private static final long serialVersionUID = 1L; //Student id private long id; //Student age private int age; //Student name private String name; public long getId() { return id; } public void setId(long id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Client main function
public class Client { public static void main(String[] args) { Service service = (Service) Stub.getService(Service.class); Student student = service.queryStudentById(123); System.out.println(JSON.toJSONString(student)); } }
Code required by the server
//Server public class Server { public static void main(String[] args) throws Exception { ServerSocket serverSocket = new ServerSocket(4396); while (true) { handle(serverSocket.accept()); } } /** * Processing request method * @param socket Connect socket * @throws Exception */ public static void handle(Socket socket) throws Exception { ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream()); //Get parameters String clazzName = objectInputStream.readUTF(); String methodName = objectInputStream.readUTF(); Class[] paramTypes = (Class[]) objectInputStream.readObject(); Object[] args = (Object[]) objectInputStream.readObject(); //Get the service implementation class through spi Class<?> aClass = Class.forName(clazzName); ServiceLoader<?> serviceLoader = ServiceLoader.load(aClass); Object studentService = null; for (Object service : serviceLoader) { studentService = service; } if (studentService == null) { System.out.println("Service not found"); return; } //Get the method to be called Method method = studentService.getClass().getMethod(methodName, paramTypes); Object invoke = method.invoke(studentService, args); //Send return value ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream()); objectOutputStream.writeObject(invoke); //Close flow objectInputStream.close(); objectOutputStream.close(); } }
Called interface
Interface
public interface Service { /** * Get student object * @param id Student id * @return */ Student queryStudentById(long id); }
Interface implementation
public class StudentService implements Service{ @Override public Student queryStudentById(long id) { Student student = new Student(); student.setId(4396); student.setAge(27); student.setName("Zhang San"); return student; } }
Entity class
public class Student implements Serializable { private static final long serialVersionUID = 1L; //Student id private long id; //Student age private int age; //Student name private String name; public long getId() { return id; } public void setId(long id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
SPI profile
com.example.demo.rpc.StudentService