Skip to content
On this page

Dynamic Proxy

Let’s compare the differences between Java class and interface :

  • Can instantiate class (non abstract );
  • Cannot instantiate interface .

All interface type variables are always upcast through an instance and assigned to interface type variables:

java
CharSequence cs = new StringBuilder();

Is it possible to create an instance of an interface directly at runtime without writing an implementation class?

This is possible because the Java standard library provides a dynamic proxy (Dynamic Proxy) mechanism: an instance of an interface can be dynamically created during runtime.

What is runtime dynamic creation? It sounds complicated. The so-called dynamic proxy corresponds to static. Let’s see how to write static code:

Define interface:

java
public interface Hello {
    void morning(String name);
}

Write implementation class:

java
public class HelloWorld implements Hello {
    public void morning(String name) {
        System.out.println("Good morning, " + name);
    }
}

Create an instance, convert it to an interface and call:

java
Hello hello = new HelloWorld();
hello.morning("Bob");

This way is how we usually write code.

Another way is dynamic code. We still define the interface Hello first, but we do not write an implementation class. Instead, we create a Hello interface object directly through a Proxy.newProxyInstance() provided by the JDK. This method that does not implement a class but dynamically creates an interface object during runtime is called dynamic code. The method provided by JDK to dynamically create interface objects is called dynamic proxy.

One of the simplest dynamic proxy implementations is as follows:

java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Main {
    public static void main(String[] args) {
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println(method);
                if (method.getName().equals("morning")) {
                    System.out.println("Good morning, " + args[0]);
                }
                return null;
            }
        };
        Hello hello = (Hello) Proxy.newProxyInstance(
            Hello.class.getClassLoader(), // Pass in ClassLoader
            new Class[] { Hello.class }, // Pass in the interface to be implemented
            handler); // Pass in the InvocationHandler that handles the calling method
        hello.morning("Bob");
    }
}

interface Hello {
    void morning(String name);
}

The method to dynamically create an interface instance at runtime is as follows:

  • Define an InvocationHandler instance, which is responsible for implementing the method invocation of the interface;
  • Create an interface instance through Proxy.newProxyInstance() , which requires 3 parameters:
    • ClassLoader used is usually ClassLoader of the interface class;
    • The array of interfaces that need to be implemented requires at least one interface to be passed in;
    • InvocationHandler instance used to handle interface method calls.
  • Cast the returned Object into an interface.

Dynamic proxy is actually a process in which the JVM dynamically creates class bytecode and loads it during runtime. There is no black magic in it. Rewriting the above dynamic proxy into a static implementation class probably looks like this:

java
public class HelloDynamicProxy implements Hello {
    InvocationHandler handler;
    public HelloDynamicProxy(InvocationHandler handler) {
        this.handler = handler;
    }
    public void morning(String name) {
        handler.invoke(
           this,
           Hello.class.getMethod("morning", String.class),
           new Object[] { name }
        );
    }
}

In fact, the JVM automatically writes the above class for us (no source code is required, bytecode can be directly generated), and there is no black magic that can directly instantiate the interface.

Summary

The Java standard library provides a dynamic proxy function, allowing an instance of an interface to be dynamically created during runtime;

Dynamic proxy is accomplished by creating a proxy object through Proxy , and then "proxying" the interface method to InvocationHandler .

Dynamic Proxy has loaded