Proxy mode is a very important design pattern, which has a wide application in the Java language, including the core design idea of Spring AOP, and is closely related to the proxy mode.
There are two main types of proxy mode: static agent and dynamic agent. There are essential differences in the implementation of two kinds of proxy methods.
The role of proxy mode is to provide a proxy for other objects to control access to this object. In some cases, a customer does not want or cannot refer to another object directly, and the proxy object can be
acts as an intermediary between the client and the target object.
The agent model generally involves the following roles:
abstract Role: a common interface for declaring real objects and proxy objects.
Proxy Role: the Proxy object role contains a reference to the real object, allowing you to manipulate the real object while the proxy object provides the same interface as the real object to replace the real at any moment
the like. At the same time, the proxy object can attach other actions when performing the real object operation, which is equivalent to encapsulating the real object.
Real role: the real object represented by the proxy role is the object we end up referencing.
First, static agent
The static proxy agent and the Proxied object are determined before the agent. They all implement the same interface or inherit the same abstract class.
/** * Abstract Role */public abstract class Subject {abstract public void request ();}/** * Real role: Implements the Subject request () method */publi C Class Realsubject extends Subject {public realsubject () {} public void request () {System.out.printl N ("The request method of the real role Realsubject.request () is called!"); }}/** * Proxy role */public class Proxysubject extends Subject {private realsubject realsubject;//attribute pub with real role as proxy role Lic Proxysubject () {}//The method encapsulates the request method of the real object public void request () {prerequest (); Actions performed before the agent if (realsubject = = null) {Realsubject = new realsubject (); } realsubject.request (); The request method for executing the real object here Postrequest (); Action performed after the agent} private void Prerequest () {//something you want to do before requesting SYSTEM.OUT.PRI NTLN ("Action performed before Agent Proxysubject.prerequest ()!"); } private void Postrequest () {//something you want to does after requesting SYSTEM.OUT.PRINTLN ("ProxyAfter performing the Operation Proxysubject.postrequest ()! ");}} /** * Client calls */public class client {public static void main (string[] args) {Subject sub = new Proxysubject (); Sub.request (); }}
Run the client call with the following results:
Action performed before the Agent Proxysubject.prerequest ()!
The request method of the real role Realsubject.request () is called!
Action performed after the Agent Proxysubject.postrequest ()!
The code content is very simple, from the above code can be seen, the customer actually need to call the Realsubject class request () method, now use Proxysubject to Proxy Realsubject class, also achieve the purpose, but also encapsulated other methods ( Prerequest (), Postrequest ()), can handle some other problems.
In addition, if you want to use the proxy mode as described above, the real role must be pre-existing and used as the internal property of the proxy object. But when used in practice, a real role must correspond to a proxy role, and if a large number of uses would cause the class to swell dramatically, how would you use a proxy if you didn't know the real role beforehand? This problem can be solved by the dynamic proxy class in Java. Take a look at the dynamic proxy mode below.
Second, dynamic agent
The Java dynamic proxy class is located under the Java.lang.reflect package, which generally involves the following two classes:
(1) Interface Invocationhandler: Only one method is defined in this interface
public object Invoke (object Obj,method Method, object[] args)
When actually used, the first parameter, obj, generally refers to the proxy class, which method is the proxy, as in the previous example, the request (), args is the parameter array for the method. This abstract method is implemented dynamically in the proxy class.
(2) Proxy: This class is a dynamic proxy class that acts like the proxysubject in the previous example, which mainly contains the following
Dynamic proxy Classes
Protected Proxy (Invocationhandler H): constructor, used to assign values to internal H.
Static class Getproxyclass (ClassLoader loader, class[] interfaces): Gets a proxy class, where loader is a class loader, and interfaces is an array of all the interfaces owned by the real class.
Static Object newproxyinstance (ClassLoader loader, class[] interfaces, Invocationhandler h): Returns an instance of the proxy class, The returned proxy class can be used as a proxy class (a method declared in the subject interface can be used by the proxy class)
Dynamic proxy Classes
The so-called dynamic Proxy is a class that is generated at runtime and you have to provide a set of interface to it when it is generated, and then the class declares that it implements these interface. You can certainly use this class instance as any of these interface. Of course, this dynamic proxy is actually a proxy, it will not do a substantial job for you, in the generation of its instance you must provide a handler, it takes over the actual work
When using dynamic proxy classes, we must implement the Invocationhandler interface.
Here is an example of changing the static proxy to a dynamic proxy:
/** * Abstract Role */public interface Subject {public void request ();}/** * Specific role: proxy class */public class Realsubject implements S ubject {public realsubject () {} public void request () {System.out.println ("requested method for the specific role realsubject.reques T () is called! ");}} /** * Proxy Processor * * The internal property of the proxy class is the object class, which is actually assigned by the constructor of the class Dynamicsubject (object obj); * In addition, the Invoke method is implemented in the class, and the method Method.invoke (Sub,args); * is actually called the object to be executed by the method, the method parameter sub is the actual proxy object, * args for the execution of the proxy object corresponding operation required parameters. * With dynamic proxy classes, we can perform some related operations before or after the call * * public class Dynamicsubject implements Invocationhandler {private Object sub; The proxy object public Dynamicsubject () {}/** * constructs the method and initializes the Proxied object * @param obj is the proxied object */Public Dynamic Subject (Object obj) {sub = obj; }/** * * @param proxy refers to the agent class * @param method being proxied * @param the parameter array required by the method of args being proxied * @return in proxy real Example, the method call is processed and the result is returned. * @throws Throwable */Public object Invoke (object proxy, Method method, object[] args) throws Throwable { System.out.println ("actions performed before the agent!"); Method.invoke (sub, args); SYSTEM.OUT.PRINTLN ("Action performed after agent!"); return null; }}/** * Client */public class Client {static public void main (string[] args) throws Throwable {Realsubject rs = new Realsubject (); Specify the proxy class here//Declare a proxy class object through the proxy class object Invocationhandler Dynamicsubject = new Dynamicsubject (RS); Class<?> cls = Rs.getclass (); The following is a one-time generation of proxy class instances://Returns a proxy class instance of a specified interface that can assign a method call to a specified invocation handler. Subject Subject = (Subject) proxy.newproxyinstance (Cls.getclassloader (),//class loader that defines the proxy class Cls.getinterfaces (),//proxy class to implement the interface list dynamicsubject); Call handler for assigning method calls: Invocationhandler object Subject.request (); Invoke the method on the proxy processor}}
Operation Result:
Actions performed before the agent!
The request method for the specific role realsubject.request () is called!
Actions performed after the agent!
To summarize, the steps of the dynamic agent implementation
1. Create a class that implements the interface Invocationhandler, which must implement the Invoke method
2. Create the class and interface that is being proxied.
3. static method through Proxy.
Newproxyinstance (ClassLoader loader, class[] interfaces, Invocationhandler h) Create a proxy class.
4. Invoke the method through the proxy.
----Proxy mode of exploring design patterns