Let's look at another way to proxy Java--jdk dynamic Proxy
The proxy method we described earlier is called a static proxy, which is a static build proxy object, while a dynamic proxy creates a proxy object at run time. Dynamic proxies have a more powerful interception request function, because the runtime information of the class can be obtained, which can be used to obtain a more powerful (operating) force (acting).
Let's take the example above, where both the Istars interface and the Stars class do not need to be modified, only the proxy class needs to be modified.
Creating a JDK dynamic agent requires implementing the Invocationhandler interface first and overriding the Invoke method in the following steps:
1. Create a class to implement the Invocationhandler interface.
2. Give the proxy class the ClassLoader and interfaces of the delegate class to create a dynamic proxy class.
3. Use the reflection mechanism to get the constructor of the dynamic proxy class.
4. Create a dynamic proxy class object with the constructor of the dynamic proxy class.
We use dynamic proxies to transform the previous classes:
Interfaces and delegate classes do not need to be modified:
Public Interface istars { void sing (); void dance ();}
Public classStarsImplementsistars{PrivateString name; PublicStars (String name) { This. Name =name; } PublicString GetName () {returnname; } Public voidsetName (String name) { This. Name =name; } Public voidSing () {System.out.println (GetName ()+ "sang a song."); } Public voidDance () {System.out.println (GetName ()+ "a dance."); }}
This is the proxy class after using the dynamic proxy:
Public classStarsnewproxyImplementsInvocationhandler {//the proxy class holds the object reference for the delegate class PrivateObject object; //number of sing and dance saved Private intnum; PublicStarsnewproxy (Object object) { This. Object =object; } @Override PublicObject Invoke (Object proxy, Method method, object[] args)throwsThrowable {if(!Runbefore (method)) { return NULL; }; //using the reflection mechanism to assign the request to the delegate class processing, the invoke of method returns the object as the result of the method executionObject result =Method.invoke (Object,args); RunAfter (method); returnresult; } Private BooleanRunbefore (method) {System.out.println ("I am the agent, intercept to the request"); if(Method.getname (). Equals ("Dance") {System.out.println ("I'm sorry, the star's foot is hurt and I can't dance." "); return false; } return true; } Private voidRunAfter (method) {System.out.println ("I am the agent, request processing complete"); }}
Create a new factory class to return the proxy instance:
Public classStarsnewproxyfactory {//Building the factory class, the client class calls this method to get the proxy object//for the client class, the proxy class object is the same as the delegate class object, and you do not need to know the type of the specific return Public Staticistars getinstance (String name) {Istars stars=NewStars (name); Invocationhandler Handler=NewStarsnewproxy (stars); Istars Proxy=NULL; Proxy=(Istars) proxy.newproxyinstance (Stars.getclass (). getClassLoader (), Stars.getclass (). g Etinterfaces (), handler); returnproxy; }}
Rewrite the test class:
Public classTest { Public Static voidMain (string[] args) {//TestA ();Testb (); } /*** Static proxy*/ Private Static voidTestA () {//To Create a target objectIstars stars =NewStars ("Frank"); //proxy object, pass the target to the proxy object, establish the relationshipIstars Starsproxy =NewStarsproxy (stars); for(inti = 0;i < 5; i++) {starsproxy.sing (); } } /*** JDK Dynamic Agent*/ Private Static voidTestb () {Istars proxy= Starsnewproxyfactory.getinstance ("Frank"); Proxy.dance (); Proxy.sing (); }}
The output is as follows:
I am the agent, intercept to request sorry, star foot injured, can not dance performance. I am the agent, intercept to ask Frank to sing a song. I am the agent, request processing finished
When using dynamic proxy, the Invocationhandler interface is implemented and the Invoke method is written with the three parameters of the Invoke method:
throws Throwableproxy: The object method that is being proxied: Methods object of one of the proxy objects args: Parameters accepted by a method of a proxy object
The Newproxyinstance method details of proxy are as follows:
Public Static throws Illegalargumentexceptionloader: A ClassLoader object that defines which ClassLoader object to load the generated proxy object interfaces: An array of interface objects , which means I'm going to provide a set of interfaces to the object I need to proxy, and if I provide a set of interfaces to it, then the proxy object declares that it implements the interface (polymorphic) so I can invoke the method in this set of Interfaces H: A Invocationhandler object, Indicates which Invocationhandler object the dynamic proxy object will be associated with when calling the method.
As you can see, the dynamic agent here, like the static proxy, holds an instance of the delegate class inside the proxy class, actually calls the original delegate instance to do the required operation, the proxy class is equivalent to the delegate class with a shell, the delegate class is placed inside the proxy class, so that the client class access to the delegate class can be controlled, As in the example above, the proxy class intercepts the client class's access to the dance method of the Stars class and outputs supplemental information.
The biggest difference between dynamic agent and static agent is that the time of generating proxy class is different, static agent is at compile time, and dynamic agent is dynamically generated at runtime according to the information of delegate class.
Secondly, the dynamic agent realizes the Invocationhandler interface, while the static agent realizes the public interface directly. Of course, dynamic agents also need to implement the same interface, just put the interface information inside the getinstance, equivalent to the proxy class and the contract between the class, "these several methods to help me agent it."
Finally, dynamic agents can obtain more runtime information and are more flexible to use.
At this point, the JDK dynamic agent explained, welcome to continue to pay attention!
"Getting Started with Java" Day11 Java Agent--jdk dynamic agent