Dynamic proxy Classes
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 the interface:
Object Invoke (Object proxy, 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, request (), args is the parameter array for the method (NULL when no parameter is set).
This abstract method is implemented dynamically in the proxy class.
2.Proxy
The class is a dynamic proxy class that acts like the proxysubject in the example above, which mainly includes the following:
Protected Proxy (Invocationhandler H): constructor, used to assign values to internal invocation handler.
Static class<?> Getproxyclass (ClassLoader loader, class<?> .... Interfaces): Loader is a class loader, 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 (you can use the method declared by the proxy class in the subject interface).
Dynamic proxy class Description
The so-called dynamic Proxy is a class:
It is the class generated at runtime and you must 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. Each dynamic proxy class will have a invocation handler associated with it.
The real call is done in the Invoke () method of the invocation handler.
Dynamic Agent Steps
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. Create a proxy through the static method of proxy newproxyinstance (ClassLoader loader, class<?>[] interfaces, Invocationhandler h).
4. Invoke the method through the proxy.
Dynamic Proxy Example 1:
First define the abstract role and the real role class:
Public interface subject{public void request ();
public class Realsubject implements subject{ @Override public Void request () { System.out.println (" From real subject! ");} }
Then define a Dynamicsubject class:
Import Java.lang.reflect.invocationhandler;import java.lang.reflect.method;/** * The internal properties of the proxy class are of type object, The actual use of this class through the construction method passed in an object. * This class implements the Invoke () method, in which Method.invoke () is actually the method to invoke the object being proxied, and the method parameter sub indicates that the method belongs to a sub. * With dynamic proxy classes, we can add some additional methods to the real object before and after the method * */public class Dynamicsubject implements invocationhandler{ //references to real objects private Object Sub; Public dynamicsubject (Object obj) { this.sub = obj; } @Override Public object Invoke (Object proxy, Method method, object[] args) throws Throwable { System.out.println ("before calling:" + method); Method Method.invoke (sub, args) is invoked by reflection; System.out.println ("After calling:" + method); return null;} }
When used:
Import Java.lang.reflect.invocationhandler;import Java.lang.reflect.proxy;public class client{public static void Main (string[] args) { Realsubject realsubject = new Realsubject (); Invocationhandler handler = new Dynamicsubject (realsubject); class<?> ClassType = Handler.getclass (); The build agent //dynamically generates a class (implements the specified interface), generates the class object, translates to interface type Subject Subject = (Subject) proxy.newproxyinstance (ClassType . getClassLoader (), Realsubject.getclass (). Getinterfaces (), handler); Subject.request (); When the method is called, it is transferred to the handler takeover by the Invoke () method where the actual completion method executes System.out.println (Subject.getclass ());//Print out: Class $Proxy 0 //$Proxy 0 is a dynamically generated class during runtime }}
In this way, the Proxied object (Realsubject) can be dynamically changed at runtime, the interface that needs to be controlled (subject interface) can be changed at runtime, the control mode (Dynamicsubject Class) can also be changed dynamically, thus realizing a very flexible dynamic agent relationship.
Dynamic Proxy Implementation Example 2:
In this example, an interface is defined:
Public interface foo{public void DoAction ();}
This interface has two implementation classes:
public class FOOIMPL1 implements foo{ @Override public void DoAction () { System.out.println (' from Implement 1! ");} public class FOOIMPL2 implements foo{ @Override public void DoAction () { System.out.println (' from Implement 2! ");}
Defines the invocation handler, where the set method makes the actual object replaceable:
Import Java.lang.reflect.invocationhandler;import Java.lang.reflect.method;public class Commoninvocationhandler Implements invocationhandler{ private Object target; Public Commoninvocationhandler () { } public Commoninvocationhandler (Object obj) { This.target = obj; } public void Settarget (Object target) { this.target = target; } @Override Public object Invoke (Object proxy, Method method, object[] args) throws Throwable { Return Method.invoke (target, args);} }
Use:
Import Java.lang.reflect.proxy;public class demo{public static void Main (string[] args) { Commoninvocationhandler handler = new Commoninvocationhandler (); Foo f = null; Handler.settarget (New FooImpl1 ()); f = (Foo) proxy.newproxyinstance (Foo.class.getClassLoader (), new class[] {Foo.class}, handler); F.doaction (); System.out.println ("----------------------------"); Handler.settarget (New FooImpl2 ()); F.doaction (); }}
After running the program output:
From Implement 1!
----------------------------
From Implement 2!
Dynamic Proxy Implementation Example 3:
1, Bookfacade.java
Public Interface publicvoid addbook (); }
2, Bookfacadeimpl.java
Public class Implements Bookfacade { @Override publicvoid Addbook () { System.out.println ("Add Book Method ... "); } }
3, Bookfacadeproxy.java
PackageNet.battier.proxy; ImportJava.lang.reflect.InvocationHandler; ImportJava.lang.reflect.Method; ImportJava.lang.reflect.Proxy; /*** JDK Dynamic Proxy proxy class * *@authorStudent **/ Public classBookfacadeproxyImplementsInvocationhandler {PrivateObject Target; /*** Bind the delegate object and return a proxy class *@paramTarget *@return */ Publicobject bind (object target) { This. target =Target; //Get proxy Objectreturnproxy.newproxyinstance (Target.getclass (). getClassLoader (), Target.getclass (). Getinterfaces (), This);//to bind an interface (this is a flaw, cglib compensates for this flaw)} @Override/*** Call Method*/ Publicobject Invoke (Object proxy, Method method, object[] args)throwsthrowable {Object result=NULL; System.out.println ("Things start."); //Execution Methodresult=Method.invoke (target, args); System.out.println ("The end of things."); returnresult; } }
4, Testproxy.java
However, the dynamic proxy of the JDK relies on the interface, and if some classes do not implement the interface, then the JDK proxy cannot be used, which will use the Cglib dynamic proxy.
Cglib Dynamic Agent
The dynamic agent mechanism of JDK can only implement the class of the interface, and the class that cannot implement the interface cannot implement the dynamic proxy of the JDK, the cglib is to implement the proxy for the class, his principle is to generate a subclass for the target class, and overwrite the method implementation enhancement, but because inherit is adopted, Therefore, the final decorated class cannot be proxied.
Example
1, Bookfacadecglib.java
2, Bookcadeimpl1.java
3, Bookfacadeproxy.java
PackageNet.battier.proxy; ImportJava.lang.reflect.Method; ImportNet.sf.cglib.proxy.Enhancer; ImportNet.sf.cglib.proxy.MethodInterceptor; ImportNet.sf.cglib.proxy.MethodProxy; /*** Use cglib dynamic agent * *@authorStudent **/ Public classBookfacadecglibImplementsMethodinterceptor {PrivateObject Target; /*** Create proxy Object * *@paramTarget *@return */ Publicobject GetInstance (object target) { This. target =Target; Enhancer Enhancer=Newenhancer (); Enhancer.setsuperclass ( This. Target.getclass ()); //callback MethodEnhancer.setcallback ( This); //Create a proxy objectreturnenhancer.create (); } @Override//callback Method PublicObject Intercept (Object obj, Method method, object[] args, methodproxy proxy)throwsthrowable {System.out.println ("Things start."); Proxy.invokesuper (obj, args); System.out.println ("The end of things."); return NULL; } }
4, Testcglib.java
Packagenet.battier.test; ImportNET.BATTIER.DAO.IMPL.BOOKFACADEIMPL1; ImportNet.battier.proxy.BookFacadeCglib; Public classTestcglib { Public Static voidMain (string[] args) {bookfacadecglib cglib=NewBookfacadecglib (); BOOKFACADEIMPL1 Bookcglib= (BOOKFACADEIMPL1) cglib.getinstance (NewBookFacadeImpl1 ()); Bookcglib.addbook (); } }
Java Dynamic Agent Learning