• Uncategorised
  • 0

How Java dynamic proxy works internally

Here’s a practical example of a Java dynamic proxy used to log method calls on a real object — a common pattern in frameworks like Spring AOP.


🎯 Scenario

You have a service:

public interface PaymentService {
void pay(String account, double amount);
}

Implementation:

public class PaymentServiceImpl implements PaymentService {
public void pay(String account, double amount) {
System.out.println("Transferring ₹" + amount + " to " + account);
}
}

Now you want to log each method call without changing the original class.


✅ Proxy + Logging Example

import java.lang.reflect.*;

public class LoggingInvocationHandler implements InvocationHandler {
private Object target;

public LoggingInvocationHandler(Object target) {
this.target = target;
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(">> Invoking " + method.getName() + " with " + java.util.Arrays.toString(args));
Object result = method.invoke(target, args);
System.out.println("<< Done with " + method.getName());
return result;
}

public static void main(String[] args) {
PaymentService realService = new PaymentServiceImpl();

PaymentService proxy = (PaymentService) Proxy.newProxyInstance(
PaymentService.class.getClassLoader(),
new Class[] { PaymentService.class },
new LoggingInvocationHandler(realService)
);

proxy.pay("uday@bank", 5000);
}
}

🧾 Output

>> Invoking pay with [uday@bank, 5000.0]
Transferring ₹5000.0 to uday@bank
<< Done with pay

💡 Real-world Usage

FrameworkHow it uses dynamic proxy
Spring AOPMethod interception (e.g. @Transactional)
JPA/HibernateLazy-loading proxies for entities
MockitoMocks using dynamic proxies
Java RMIRemote stubs

👉 In this dynamic proxy example, Java generates a new class at runtime, and this class:

  • Implements the specified interface(s) (PaymentService)
  • Delegates all method calls to your custom InvocationHandler

🏗 Who generates the class?

The class is created by the JDK Proxy API:

Proxy.newProxyInstance(...)

Under the hood, this dynamically creates a class similar to:

javaCopyEditclass $Proxy123 implements PaymentService {
    InvocationHandler handler;

    public $Proxy123(InvocationHandler handler) {
        this.handler = handler;
    }

    public void pay(String account, double amount) {
        // Delegates to your handler
        handler.invoke(this, PaymentService.class.getMethod("pay", ...), new Object[]{account, amount});
    }
}

This $Proxy123 class:

  • Did not exist in your code
  • Is generated and loaded at runtime
  • Is stored in memory (not saved as a .class file unless debugging is enabled)

🧠 Where is it stored?

  • It’s created by ProxyGenerator (an internal JDK class)
  • Loaded by an internal ClassLoader
  • Assigned a synthetic class name like $Proxy1, $Proxy2, etc.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *