Proxy mode (static proxy and dynamic proxy)
I. Proxy Mode
Proxy is a common design pattern, which aims to provide a proxy for other objects to control access to an object. The proxy class is responsible for preprocessing messages for the delegate class, filtering messages and forwarding messages, and subsequent processing after the message is executed by the delegate class.
A static proxy can only represent one type of proxy, and is the object that has been identified by the compiler. Dynamic proxy is used to implement dynamic proxy through the reflection mechanism at runtime, and can proxy various types of objects.
Ii. Static proxy
The source code of the proxy class is generated by a programmer or a tool, and then the proxy class is compiled. Static means that the bytecode file of the proxy class already exists before the program runs. The relationship between the proxy class and the delegate class is determined before the program runs.
Class Diagram of static proxy
Static proxy code(Here, only the main code is pasted. The source code is attached with the link address. If you are interested, you can download it)
Package StaticProxy;/*** @ ClassName: Proxy * @ Description: proxy class * @ author zhangbo-huaxiangniaoyu0109@126.com * @ date May 26, 2015 2:52:10 */public class Proxy implements Subject {private RealSubject realSubject; // The compiler has determined the specific delegate class public Proxy (RealSubject realSubject) {this. realSubject = realSubject;} @ Overridepublic void giveGift () {realSubject. giveGift ();}}
Disadvantages of static proxy: If you add a method to the interface (comment out all the code above), you must implement all the implementation classes and proxies. This increases the complexity of the Code. Dynamic proxy can avoid this disadvantage.
3. Dynamic proxy
The source code of the dynamic proxy class is dynamically generated by JVM according to reflection and other mechanisms during the program running, so there is no bytecode file of the proxy class. The relationship between the proxy class and the delegate class is determined when the program is running.
To implement the dynamic Proxy mechanism in Java, java. lang. reflect. InvocationHandler interface and java. lang. reflect. Proxy class are required.
The java. lang. reflect. InvocationHandler interface is defined as follows:
public interfaceInvocationHandler { public Object invoke(Object proxy, Methodmethod, Object[] args) throws Throwable;}
Objectproxy: the proxy object (delegate class)
Methodmethod: method to be called (delegate class)
Object [] args: parameters required for method calling
Java. lang. reflect. Proxy class is defined as follows: -- get Proxy object
public static ObjectnewProxyInstance(ClassLoader loader, Class
[] interfaces,InvocationHandler h) throws IllegalArgumentException
CLassLoaderloader: Class Loader (delegate class)
Class Interfaces: Get all interfaces (delegate class)
InvocationHandlerh: obtains the instance (proxy class) of the subclass of the InvocationHandler interface)
After reading this, we will first draw a dynamic proxy diagram of the first version:
This is the dynamic proxy class diagram I drew in the first version. to display the delayed loading of the dynamic proxy and decouple it from the real class, I used the client, to indicate that the real class to be removed from the instance during running, and the relationship between the dynamic proxy class and the real class will occur. However, this class diagram lacks some classes. Since it is a class diagram, the Proxy class we mentioned earlier is not shown here. So I improvedDynamic proxy Diagram for version 2:
This figure shows the Proxy and InvocationHandler classes, and shows the principle of how InvocationHandler and Proxy implement dynamic Proxy.
Some people say that the Code is the best teacher. Maybe some people still don't quite understand this figure. It doesn't matter. Just read the code. (here, only the main code is posted, and the source code is attached with the link address, if you are interested, you can download it ):
Package DynamicProxy; import java. lang. reflect. invocationHandler; import java. lang. reflect. method;/*** @ ClassName: DynamicProxy * @ Description: dynamic proxy class * @ author Zhang thin-huaxiangniaoyu0109@126.com * @ date May 26, 2015 8:34:21 */public class DynamicProxy implements InvocationHandler {private Object obj; // delegate class // specific instructions introduce the class, however, no specific delegate class is specified. It is dynamically loaded into public DynamicProxy (Object obj) {this. obj = obj ;}@ Overridepublic Object invoke (Object proxy, Method method, Object [] args) throws Throwable {System. out. println (obj: + obj. getClass (). getName (); System. out. println (proxy: + proxy. getClass (). getName (); System. out. println (method: + method. getName (); System. out. println (args: + args); // obtain all methods and parameters of the delegate Class Object result = method. invoke (this. obj, args); return result ;}}
Package DynamicProxy; import java. lang. reflect. invocationHandler; import java. lang. reflect. proxy;/*** @ ClassName: Client * @ Description: Specifies the delegate class used by the Proxy class on the Client, and the method used to delay loading. Dynamic and flexible configuration. * @ Author Zhang Bo-huaxiangniaoyu0109@126.com * @ date May 26, 2015 8:39:45 */public class Client {public static void main (String [] args) {// declare and instantiate the delegate class Subject realSubject = new RealSubject (); // obtain the class loader of the delegate class to run and load the bytecode ClassLoader loader = realSubject on the virtual machine. getClass (). getClassLoader (); // obtain all the interface classes of the delegate Class to implement all the methods of the Interface Class.
[] Interfaces = realSubject. getClass (). getInterfaces (); // instantiate the proxy class InvocationHandler handler = new DynamicProxy (realSubject); // dynamically load the selected delegate class to the proxy class for flexible configuration, dynamically load Subject dynamicProxy = (Subject) Proxy. newProxyInstance (loader, interfaces, handler); // execute the proxy method dynamicProxy. giveGift ();}}