This article is from: Cao shenghuan blog column. Reprinted please indicate the source:Http://blog.csdn.net/csh624366188
Proxy Design 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.
The proxy mode provides a proxy for other objects to control access to this object. In some cases, a client does not want or cannot directly reference another object, and the proxy object can play a mediation role between the client and the target object.
The proxy mode generally involves the following roles:
Abstract role: Declares the common interfaces of real objects and proxy objects;
Proxy role: the proxy object role contains a reference to the real object to operate on the real object. At the same time, the proxy object provides the same interface as the real object to replace the real object at any time. At the same time, the proxy object can append other operations when performing real object operations, which is equivalent to encapsulating real objects.
Real role: the real object represented by the proxy role is the object we finally want to reference
Figure 1. Proxy mode class diagram
To maintain behavior consistency, the proxy class and the delegate class usually implement the same interface, so there is no difference between the two in the visitor's opinion. Through the intermediary layer of the proxy class, direct access to the delegate class objects can be effectively controlled, the delegate class objects can be well hidden and protected, and space is reserved for implementing different control policies, in this way, more flexibility is achieved in design. Java Dynamic proxy mechanism almost perfectly practices the design concept of proxy mode in a clever way.
Java Dynamic proxy
Related Classes and interfaces
To understand the Java Dynamic proxy mechanism, you must first understand the following related classes or interfaces:
· Java. Lang. Reflect. Proxy: This is the main class of the Java Dynamic proxy mechanism. It provides a set of static methods to dynamically generate proxy classes and objects for a group of interfaces.
Listing 1. Static proxy method
// Method 1: This method is used to obtain the call processor static invocationhandler getinvocationhandler (Object proxy) associated with the specified proxy object. // Method 2: this method is used to obtain the static class getproxyclass (classloader loader, class [] interfaces) Class Object associated with the specified class loader and a group of interfaces. // method 3: this method is used to determine whether the specified class object is a dynamic proxy class static Boolean isproxyclass (class Cl) // Method 4: this method is used to generate a static object newproxyinstance (classloader loader, class [] interfaces, invocationhandler H) for the specified class loader, a group of interfaces, and call the processor)
Java. lang. reflect. invocationhandler: this is the call processor interface. It customizes an invoke Method for centralized processing of method calls on dynamic proxy objects. Generally, this method implements proxy access to the delegate class.
Listing 2. Core methods of invocationhandler
// This method is used to centrally process all method calls in the dynamic proxy class. The first parameter is a proxy instance, and the second parameter is the called method object // The third method is the call parameter. The call Processor Pre-processes these three parameters or assigns them to the delegate class instance to launch and execute the object invoke (Object proxy, method, object [] ARGs)
Each time a dynamic proxy class object is generated, you must specify a processor object for calling the interface (see the third parameter of proxy static method 4 ).
· Java. Lang. classloader: This Class Loader class. It is responsible for loading the class bytecode to the Java Virtual Machine (JVM) and defining class objects for it before the class can be used. The dynamic proxy class generated by the proxy static method also needs to be loaded by the class loader for use, the only difference between it and common classes is that its bytecode is dynamically generated by the JVM at runtime, rather than pre-stored in any. class file.
Each time a dynamic proxy class object is generated, a Class Loader object needs to be specified (see the first parameter of proxy static method 4)
Proxy Mechanism and Its Features
First, let's take a look at how to use Java Dynamic proxy.The procedure is as follows:
1. Create your own call processor through the invocationhandler interface;
2. Create a dynamic proxy class by specifying a classloader object and a group of interfaces for the proxy class;
3. Obtain the constructor of the dynamic proxy class through the reflection mechanism. The unique parameter type is the type of the called processor interface;
4. Create a dynamic proxy instance by using the constructor. During the constructor, the processor object called as a parameter is passed in.
Listing 3. Dynamic proxy object creation process
// Invocationhandlerimpl implements the invocationhandler interface and can distribute and forward method calls from the proxy class to the delegate class. // It usually contains references pointing to the delegate class instance, call invocationhandler handler = new invocationhandlerimpl (...) to really execute the method forwarded by the dispatch (..); // use proxy to dynamically create the Class Object Class clazz = proxy for a group of interfaces including interface interfaces. getproxyclass (classloader, new class [] {interface. class ,...}); // obtain the constructor = clazz from the generated class object through reflection. getconstructor (new class [] {invocationhandler. class}); // create a dynamic proxy instance through the constructor object interface proxy = (interface. newinstance (new object [] {handler });
The actual use process is simpler, because the static proxy method newproxyinstance has encapsulated steps 2 to 4 for us, so the simplified process is as follows:
Listing 4. Simplified process of creating dynamic proxy objects
// Invocationhandlerimpl implements the invocationhandler interface, and can implement the dispatch and forwarding of method calls from the proxy class to the delegate class. invocationhandler handler = new invocationhandlerimpl (..); // directly create a dynamic proxy instance interface proxy = (Interface) proxy through proxy. newproxyinstance (classloader, new class [] {interface. class}, Handler );
Let's take a simple example of implementing dynamic Proxy:
1. proxy class and real class interface:
public interface Subject{public void request();}
2. Real class:
public class RealSubject implements Subject{public void request(){System.out.println("From real subject!");}}
3. Specific agent class:
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class DynamicSubject implements InvocationHandler{private Object sub;public DynamicSubject(Object obj){this.sub = obj;}public Object invoke(Object proxy, Method method, Object[] args)throws Throwable{System.out.println("before calling: " + method);method.invoke(sub, args); System.out.println(args == null); System.out.println("after calling: " + method);return null;}
Note: The internal attribute of this proxy class is of the object type. In actual use, an object is transmitted through the constructor of this class. In addition, this class implements the invoke method. invoke is actually calling the method to be executed by the proxy object. The method parameter is sub, indicating that the method belongs to the sub, through the dynamic proxy class, we can add some additional methods before and after executing the real object method.
4. Client call example:
Import Java. lang. reflect. invocationhandler; import Java. lang. reflect. proxy; public class client {public static void main (string [] ARGs) {realsubject = new realsubject (); invocationhandler handler = new dynamicsubject (realsubject); Class <?> Classtype = handler. getclass (); // the following code generates the proxy subject = (subject) proxy at a time. newproxyinstance (classtype. getclassloader (), realsubject. getclass (). getinterfaces (), Handler); Subject. request (); system. out. println (subject. getclass ());}}
Next, let's take a look at the Java Dynamic proxy construction method:
Listing 6. Proxy Constructor
// Because the proxy never directly calls the constructor internally, the private type means that any call to the private proxy () {}// since the proxy never directly calls the constructor internally, so protected means that only the subclass can call protected proxy (invocationhandler h) {This. H = H ;}
Next, you can quickly browse the newproxyinstance method because it is quite simple:
Listing 7. Proxy static method newproxyinstance
Public static object newproxyinstance (classloader loader, class <?> [] Interfaces, invocationhandler h) throws illegalargumentexception {// check H is not empty; otherwise, an exception if (H = NULL) {Throw new nullpointerexception ();} // obtain the proxy class object class Cl = getproxyclass (loader, interfaces) related to the formulated class loader and a set of interfaces ); // obtain the constructor object through reflection and generate the proxy class instance try {constructor cons = Cl. getconstructor (constructorparams); Return (object) cons. newinstance (new object [] {H});} catch (nosuchmethodexception e) {Throw new internalerror (E. tostring ();} catch (illegalaccessexception e) {Throw new internalerror (E. tostring ();} catch (instantiationexception e) {Throw new internalerror (E. tostring ();} catch (invocationtargetexception e) {Throw new internalerror (E. tostring ());}}
The real key to dynamic proxy is the getproxyclass method, which dynamically generates proxy class objects for a group of interfaces.
There are many reasons that people can deny the necessity for class proxy, but there are also some reasons, I believe it will be better to support class dynamic proxy. The division of interfaces and classes is not very obvious, but it has become so refined in Java. If you only consider the declaration of a method and whether it is defined, there is a mixture of the two. Its name is abstract class. The realization of dynamic proxy for abstract classes also has its inherent value. In addition, there are some historical classes that will never be associated with dynamic proxy because no interfaces are implemented. All these are a small pity.
However, imperfection does not mean greatness. Greatness is an essence. Java Dynamic proxy is an example.