The proxy mode uses the proxy object to complete the user's request and blocks the user's access to the real object.
The proxy mode has many uses, such as for security reasons, it is necessary to block the client from directly accessing the real object; or in remote calls, the proxy object needs to be used to handle technical details in the remote method; or in order to improve the system, the real object is encapsulated to achieve the purpose of delayed loading.
When the system starts, separating the method that consumes the most resources using proxy mode can speed up the system startup speed and reduce the user's waiting time. When the user is actually doing query, the proxy class then loads the real class to complete the user request. This is the purpose of using proxy mode to achieve lazy loading.
1. Static proxy implementation:
Topic Interface:
public interface IDBQuery { String request(); } Real topic:
public class DBQuery implements IDBQuery { public DBQuery(){ try { Thread.sleep(10000); } catch (Exception e) { e.printStackTrace(); } } public String request() { return "string request"; }} Proxy class:
public class IDBQueryProxy implements IDBQuery { private DBQuery dbquery; public String request() { if(dbquery==null) dbquery = new DBQuery(); return dbquery.request(); }} Finally, the main function:
public class ProxyText { public static void main(String[] args) { IDBQuery dbquery = new IDBQueryProxy(); System.out.println(dbquery.request()); }}Static proxy note that the proxy class is a common interface for real classes to implement, and the proxy class refers to real class objects, and puts time-consuming operations in the proxy class method to implement it.
Dynamic proxy:
Dynamic proxy is when running, dynamically generates proxy classes. That is, the bytecode of the proxy class is generated and loaded at runtime. Compared with static agents, dynamic agents do not need to be careful to encapsulate a completely identical encapsulation class for the real purpose. If there are many topic interfaces, it is annoying to write a proxy method for each interface. If the interface changes, both the real class and the proxy class need to be changed, which is not conducive to system maintenance; secondly, the generation methods of some dynamic agents can even be run at runtime, which is a specified proxy class execution logic, thereby greatly improving the flexibility of the system.
Topic Interface:
public interface IDBQuery { String request(); } jdk proxy class:
public class JdbDbqueryHandler implements InvocationHandler{ IDBQuery idbquery = null; @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(idbquery==null){ idbquery = new DBQuery(); } return idbquery.request(); } public static IDBQuery createJdbProxy(){ IDBQuery jdkProxy = (IDBQuery) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{IDBQuery.class}, new JdbDbqueryHandler()); System.out.println("JdbDbqueryHandler.createJdbProxy()"); return jdkProxy; }} Main function:
public class ProxyText { public static void main(String[] args) { IDBQuery idbQuery = JdbDbqueryHandler.createJdbProxy(); System.out.println(idbQuery.request()); }}In addition, you can also use CGLIB and javassist dynamic proxy to be similar to jdk dynamic proxy, but the creation process of jdk dynamic class is the fastest, because the built-in difineclass() method is defined as a native implementation, so its performance is better than others. In the function calls of proxy classes, JDK's dynamic proxy is not as good as CGLIB and javassist dynamic proxy, while javassist dynamic proxy has the worst performance quality, and is even worse than JDK's implementation. In actual development applications, the method calling frequency of the proxy class is much higher than the actual generation frequency of the proxy class, so the method calling performance of dynamic proxy should become the focus of performance. JDK dynamic proxy mandates that proxy classes and real topics implement unified interfaces, and CGLIB and javassist dynamic proxy do not have such requirements.
In Java, the implementation of dynamic proxy involves the use of classloader. Taking CGLIB as an example, a brief description of the loading process of dynamic classes is described. Using CGLIB to generate dynamic proxy, you first need to generate an instance of the Enhancer class and formulate a callback class for handling proxy business. In the enhancer.create() method, the bytecode of the proxy class will be generated using the DefaultGeneratorStrategy.Generate() method and saved in the byte array. Then call reflectUtils.defineClass() method, and through reflection, call ClassLoader.defineClass() method to load the bytecode into the classloader to complete the loading of the class. Finally, through reflectUtils.newInstance() method, a dynamic class instance is generated by reflection and the instance is returned. Others are different from the process details, but the generation logic is the same.
The above is all about this article, I hope it will be helpful to everyone's learning.