Detailed description of Java's dynamic proxy mechanism

Keywords: Java Spring jvm

In learning Spring, we know that Spring has two main ideas, one is IoC, the other is AOP. For IoC, dependency injection needn't be said much. For Spring's core AOP, we not only need to know how to satisfy our functions through AOP, but also need to learn the underlying principle, and the principle of AOP is the motive of java. The state proxy mechanism, so this essay is a review of the dynamic mechanism of java.


In the dynamic proxy mechanism of java, there are two important classes or interfaces, one is Invocation Handler (Interface) and the other is Proxy(Class), which are necessary to implement our dynamic proxy. First, let's look at how the API Help Document of Java describes these two classes:


InvocationHandler:


InvocationHandler is the interface implemented by the invocation handler of a proxy instance. Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.


Each dynamic proxy class must implement the InvocationHandler interface, and each proxy class instance is associated with a handler. When we call a method through a proxy object, the invoke method of the InvocationHandler interface will be forwarded for invoke. Let's look at the invoke method, the only method of InvocationHandler interface:

Object invoke(Object proxy, Method method, Object[] args) throws Throwable
We see that this method accepts three parameters, so what do these three parameters represent?

Object invoke(Object proxy, Method method, Object[] args) throws Throwable
 
proxy:  Referring to the real object we represent
method:  It refers to a method that we call on a real object. Method object
args:  Refers to the parameters accepted when calling a method of a real object

If it's not clear, I'll explain these parameters more deeply through an example later.


Next, let's look at the class Proxy:


Proxy 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.


The function of Proxy class is to create a class of proxy object dynamically. It provides many methods, but the newProxyInstance method is the most used one.

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,  InvocationHandler h)  throws IllegalArgumentException

Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.


The function of this method is to get a dynamic proxy object, which receives three parameters. Let's see what these three parameters represent.

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
 
loader:  One ClassLoader Object, which defines ClassLoader Object to load the generated proxy object
 
interfaces:  One Interface An array of objects represents what interfaces I will provide to the object I need to proxy. If I provide a set of interfaces to it, the proxy object claims to have implemented the interface.(polymorphic),So I can call the methods in this set of interfaces.
 
h:  One InvocationHandler Object, which represents which dynamic proxy object I associate with when calling a method InvocationHandler On object
Well, after introducing these two interfaces (classes), let's take an example to see what our dynamic proxy model looks like:

First, we define an interface of Subject type, declaring two methods for it:

public interface Subject
{
    public void rent();
 
    public void hello(String str);
}
Then, we define a class to implement this interface. This class is our real object, RealSubject class:
public class RealSubject implements Subject
{
    @Override
    public void rent()
    {
        System.out.println("I want to rent my house");
    }
 
    @Override
    public void hello(String str)
    {
        System.out.println("hello: " + str);
    }
}
Next, we will define a dynamic proxy class. As mentioned earlier, every dynamic proxy class must implement InvocationHandler. This interface, so our dynamic proxy class is no exception:
public class DynamicProxy implements InvocationHandler
{
    //This is the real object we want to represent.
    private Object subject;
 
    //    Constructing method, assigning initial value to the real object we want to proxy
    public DynamicProxy(Object subject)
    {
        this.subject = subject;
    }
 
    @Override
    public Object invoke(Object object, Method method, Object[] args)
            throws Throwable
    {
        //We can add our own operations before proxying real objects
        System.out.println("before rent house");
 
        System.out.println("Method:" + method);
 
        //    When a proxy object invokes a method of a real object, it automatically jumps to the invoke method of the handler object associated with the proxy object for invocation.
        method.invoke(subject, args);
 
        //We can also add our own operations after proxying real objects.
        System.out.println("after rent house");
 
        return null;
    }
 
}
Finally, let's look at our Client class:
public class Client
{
    public static void main(String[] args)
    {
        //    The Real Object We Want to Act for
        Subject realSubject = new RealSubject();
 
        //    If we want to proxy which real object, we pass it in and finally call its method through the real object.
        InvocationHandler handler = new DynamicProxy(realSubject);
 
        /*
         * Using Proxy's new Proxy Instance method to create our proxy object, let's look at its three parameters
         * The first parameter, handler.getClass().getClassLoader(), is used here to load our proxy object using the ClassLoader object of the handler class.
         * The second parameter is realSubject.getClass().getInterfaces(). The interface we provide here for the proxy object is the interface implemented by the real object, indicating that I want to proxy the real object, so that I can call the methods in this set of interfaces.
         * The third parameter, handler, is the proxy object that we associate with the InvocationHandler above.
         */
        Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
                .getClass().getInterfaces(), handler);
 
        System.out.println(subject.getClass().getName());
        subject.rent();
        subject.hello("world");
    }
}
Let's first look at the console output:
$Proxy0
 
before rent house
Method:public abstract void com.xiaoluo.dynamicproxy.Subject.rent()
I want to rent my house
after rent house
 
before rent house
Method:public abstract void com.xiaoluo.dynamicproxy.Subject.hello(java.lang.String)
hello: world
after rent house
Let's first look at $Proxy0, which we see is made up of System.out.println(subject.getClass().getName()); This statement is printed out, so why do we return the class name of this proxy object?
Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
                .getClass().getInterfaces(), handler);

Maybe I thought the returned proxy object would be a Subject type object or an InvocationHandler object, but the result is not. First, let's explain why we can convert it into a Subject type object here. The reason is that on the second parameter of the new Proxy Instance method, we provide a set of interfaces for this proxy object, and then my proxy object will implement these interfaces. At this time, of course, we can convert this proxy object mandatory type into any one of these interfaces, because the interface here is a Subject type, so we can convert it. Converted to Subject type.


At the same time, we must remember that the proxy object created by Proxy. new Proxy Instance is an object dynamically generated at the jvm runtime. It is not our InvocationHandler type, nor the set of interfaces we define, but an object dynamically generated at the runtime, and its naming is in the form of $starting, proxy being the middle, and finally proxy being the last. A number represents the label of an object.


Then let's look at these two sentences.

subject.rent();
subject.hello("world");
Here is the method in the interface implemented by calling the proxy object, at which point the program will jump to the handler associated with the proxy object. The invoke method in handler is executed, and our handler object accepts a parameter of RealSubject type, indicating that the real object I want to proxy is the real object, so the invoke method in handler is called to execute at this time:
public Object invoke(Object object, Method method, Object[] args)
            throws Throwable
    {
        //We can add our own operations before proxying real objects
        System.out.println("before rent house");
 
        System.out.println("Method:" + method);
 
        //    When a proxy object invokes a method of a real object, it automatically jumps to the invoke method of the handler object associated with the proxy object for invocation.
        method.invoke(subject, args);
 
        //We can also add our own operations after proxying real objects.
        System.out.println("after rent house");
 
        return null;
    }
We see that when we call a method of a real object through a proxy object, we can add our own operations before and after the method, and we see our own. The method object is like this
public abstract void com.xiaoluo.dynamicproxy.Subject.rent()
public abstract void com.xiaoluo.dynamicproxy.Subject.hello(java.lang.String)

It's just two methods in our Subject interface, which proves that when I call a method through a proxy object, I actually delegate the invoke method of the handler object to which it relates, not to invoke it by myself, but by proxy.


This is our java Dynamic Proxy Mechanism


This essay explains the dynamic proxy mechanism in java in detail. This knowledge point is very important, including our Spring AOP, which is realized through the dynamic proxy mechanism, so we must have a good understanding of the dynamic proxy mechanism.







Posted by Fjerpje on Thu, 11 Apr 2019 14:45:31 -0700