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.
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 ThrowableThe 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 houseThe 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.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.