Backend Development 11 min read

Understanding Java Dynamic Proxy Mechanism

This article explains Java's dynamic proxy mechanism, covering the roles of InvocationHandler and Proxy classes, their APIs, the parameters required for creating proxy instances, and a complete example that demonstrates how method calls are intercepted and delegated through a custom handler.

Java Captain
Java Captain
Java Captain
Understanding Java Dynamic Proxy Mechanism

When learning Spring, we encounter two core concepts: IoC and AOP. AOP relies on Java's dynamic proxy mechanism, so this article reviews that mechanism in detail.

Java's dynamic proxy mechanism centers on two key types: the InvocationHandler interface and the Proxy class. The official API describes them as follows:

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.

The InvocationHandler interface defines a single method:

Object invoke(Object proxy, Method method, Object[] args) throws Throwable

The three parameters represent:

proxy : the proxy object itself (the real object being proxied).

method : a Method object representing the method to be invoked on the real object.

args : the arguments passed to that method.

The Proxy class provides static methods for creating dynamic proxy classes and instances, and it is the superclass of all such generated classes.

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 most commonly used method is newProxyInstance :

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 three parameters mean:

loader : the ClassLoader that will define the generated proxy class.

interfaces : an array of interfaces that the proxy class should implement.

h : the InvocationHandler that will handle method calls on the proxy.

Below is a complete example.

First, define a simple interface Subject with two methods:

public interface Subject {
    public void rent();
    public void hello(String str);
}

Then implement the interface with a real class RealSubject :

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, create a dynamic proxy class that implements InvocationHandler :

public class DynamicProxy implements InvocationHandler {
    // The real object to be proxied
    private Object subject;
    public DynamicProxy(Object subject) {
        this.subject = subject;
    }
    @Override
    public Object invoke(Object object, Method method, Object[] args) throws Throwable {
        // Pre‑processing
        System.out.println("before rent house");
        System.out.println("Method:" + method);
        // Delegate to the real object
        method.invoke(subject, args);
        // Post‑processing
        System.out.println("after rent house");
        return null;
    }
}

Finally, the client code creates the proxy and invokes methods:

public class Client {
    public static void main(String[] args) {
        // Real object
        Subject realSubject = new RealSubject();
        // Handler that wraps the real object
        InvocationHandler handler = new DynamicProxy(realSubject);
        /*
         * Create the proxy instance. The three parameters are:
         * 1) handler.getClass().getClassLoader()
         * 2) realSubject.getClass().getInterfaces()
         * 3) handler
         */
        Subject subject = (Subject) Proxy.newProxyInstance(
                handler.getClass().getClassLoader(),
                realSubject.getClass().getInterfaces(),
                handler);
        System.out.println(subject.getClass().getName());
        subject.rent();
        subject.hello("world");
    }
}

Running the program produces output similar to:

$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

The generated class name (e.g., $Proxy0 ) is printed because the proxy class is created at runtime by the JVM; it is not the original interface or handler class. The proxy implements the interfaces supplied in the second argument of newProxyInstance , which is why it can be cast to Subject .

When subject.rent() or subject.hello(...) is called, the call is intercepted by the proxy, which forwards it to the invoke method of the associated InvocationHandler . Inside invoke , custom logic can be executed before and after delegating to the real object's method via method.invoke(subject, args) . This demonstrates how Java dynamic proxies enable method interception, a technique that underlies Spring AOP.

Understanding this mechanism is essential for mastering AOP and other proxy‑based features in modern Java frameworks.

JavaProxyaopSpringDynamic ProxyInvocationHandler
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.