Java dynamic proxies are an advanced feature of the Java language. In peacetime project development, it may be difficult to encounter dynamic agent cases. But dynamic proxies play an irreplaceable role in many frameworks, such as spring's AOP. Today we'll talk about the implementation of the Java Dynamic Agent.
The JDK support for dynamic agents relies on two classes: Proxy and Invocationhandler. Let's look at the class diagram first.
The subject class is the subject class that defines what I want to do. The class that we need to Proxy is the realsubject that implements the subject interface.
1.InvocationHandler
The Invocationhandler interface is the interface provided by the JDK, and there is only one method for this interface
Public object Invoke (Object proxy, Method method, object[] args) throws Throwable;
Let's start by understanding what the Invocationhandler class is doing. The following is the Java doc
* <p>each Proxy instance have an associated invocation handler.
* When a method was invoked on a proxy instance, the method
* Invocation is encoded and dispatched to the {@code invoke}
* Method of its invocation handler.
Each proxy instance will be associated with a invocation handler, and, to be exact, each proxy class will hold a Invocationhandler instance, and the target function will be given to the Invcationhandler instance for execution. Invocationhandler only Invoke () This method, which is the method that is actually called. Whatever method the agent invokes, the handler must be called the Invoke () method. Let's take a look at the parameters of this method.
1. Object Proxy. The incoming subject reference, which is the target object that we want to actually execute.
2. Method method. Method is part of the Java Reflection API. The method object that is passed in here is actually called methods.
3. object[] args. This is an array of arguments passed in when the method is called.
After understanding the Invoke () method, the reader must be wondering how the target method of subject is called. Next we continue to understand the proxy class.
2. Proxy
Next we understand how the next proxy class works with Invocationhandler altogether. The following is a description of the proxy in Java doc:
* Provides static methods for creating dynamic proxy
* Classes and instances, and it is also the superclass of all
* Dynamic proxy classes created by those methods.
Proxy provides a static method to create a dynamic proxy class, the most common is the following method.
Public Static Object newproxyinstance (ClassLoader loader, Class<?>[] interfaces, Invocationhandler h)
With Newproxyinstance, you can dynamically create the required proxy objects and bind to the invocationhandler associated with it. The parameters are as follows
1. ClassLoader Loader, load the class loader for the proxy class.
2. class<?>[] interfaces, the interface implemented by the proxy class. The proxy class object that is created can only be strongly converted to that interfaces subclass.
3. Invocationhandler h, the invocationhandler associated with the proxy class. All proxy methods are executed through the Invocationhandler Invoke () method.
The Newproxyinstance method is the key method of generating the proxy class, and the proxy class is generated in the process of running the program and is called the dynamic Proxy.
3. Case studies
After understanding the two most important classes, we need an example to help us better understand the mechanism of dynamic agent operation.
First we create a subject interface and its implementation class.
Step 1. Define subject
1 Public InterfaceSubject {2 3 Public voidsay (String str);4 }5 6 Public classSubjectbeanImplementsSubject {7 8 @Override9 Public voidsay (String str) {Ten System.out.println (str); One } A}
Subject's say method is the way we need proxies. Before and after this method we might as well do some extra work. Next, we define our invocationhandler.
Step 2. Define Invocationhandler
1 Public classMyinvocationhandleImplementsInvocationhandler {2 3 Subject Subject;4 5 PublicMyinvocationhandle (Subject Subject) {6 This. Subject =subject;7 }8 9 @OverrideTen PublicObject Invoke (Object proxy, Method method, object[] args)throwsThrowable { OneSystem.out.println ("Pre"); A Method.invoke (subject, args); -System.out.println ("POST"); - return NULL; the } - -}
Through the constructor, the Proxied object is passed in.
Step 3. Defining a Build proxy class method implementation
Public classMain { Public StaticSubject getproxy (Subject Subject) {return(Subject) proxy.newproxyinstance (Subject.getclass (). getClassLoader (), Subject.getclass (). getinterfaces (), NewMyinvocationhandle (subject)); } Public Static voidMain (string[] args) {Subject Subject=NewSubjectbean (); Subject Proxy=GetProxy (subject); Proxy.say ("Hello"); }}
Executes the main function, and the result of the final output is:
Visible, the Say () function really method.invoke (subject, args) is done here. You can add arbitrary code fragments before and after execution to complete the enhancement of the Say () method.
4. Debug
We debug the main method to see what the proxy class is. Such as
Com.sun.proxy. $Proxy () class, which is a dynamically generated object that Proxy.newproxyinstance is called after the JVM runs, is named in this form, starting with $, proxy is medium, and the last number represents the label of the object. As for why it can be converted to subject, it is because we specify its type information in the second parameter passed in.
This article mainly describes the implementation mechanism of Java Dynamic Agent. If there is a mistake, also hope that the reader more advice.
Reference documents:
"Head First design mode"
Understanding Java Dynamic Agents