Dynamic proxy

Dynamic proxy

What is a dynamic proxy? Dynamic proxies were introduced in J2SE 1.3, and provide an alternate dynamic mechanism
for implementing many common design patterns like Façade, Bridge, Decorator, Proxy (remote proxy and virtual proxy),
and Adapter. While all of these patterns can be written using ordinary classes instead of dynamic proxies, in many
situations dynamic proxies are more compact and can eliminate the need for a lot of handwritten classes. Dynamic
proxies are reflection-based and allow you to intercept method calls so that you can interpose additional behaviour
between a class caller and its callee. Dynamic proxies are not always appropriate because this code simplification comes
at a performance cost due to reflection overhead. Dynamic proxies illustrate the basics of Aspect Oriented Programming
(AOP) which complements your Object Oriented Programming.

Where can you use dynamic proxies? Dynamic proxies can be used to add crosscutting concerns like logging,
performance metrics, memory logging, retry semantics, test stubs, caching etc. Let’s look at an example:
InvocationHandler interface is the heart of a proxy mechanism.

Proxy Handler

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Handles logging and invocation of target method
*/
public class LoggingHandler implements InvocationHandler {
protected Object actual;
public LoggingHandler(Object actual) {this.actual = actual;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
System.out.println(“>>>>>>start executing method: ” + method.getName());
Object result = method.invoke(actual, args);
return result;
} catch (InvocationTargetException ite) {
throw new RuntimeException(ite.getMessage());
} finally {
System.out.println(“<<<<<<finished executing method: ” + method.getName());
}
}
}

 

Let’s define the actual interface and the implementation class which adds up two integers.

public interface Calculator {
public int add(int i1, int i2);
}
public class CalculatorImpl implements Calculator {
public int add(int i1, int i2) {
final int sum = i1 + i2;
System.out.println(“Sum is : ” + sum);
return sum;
}
}

Factory method class CalculatorFactory, which uses the dynamic proxies when logging, is required.
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* singleton factory
*/
public class CalculatorFactory {
private static CalculatorFactory singleInstance = null;
private CalculatorFactory() {}
public static CalculatorFactory getInstance() {
if (singleInstance == null) {
singleInstance = new CalculatorFactory();
}
return singleInstance;
}
public Calculator getCalculator(boolean withLogging) {
Calculator c = new CalculatorImpl();
//use dynamic proxy if logging is required, which logs your method calls
if (withLogging) {
//invoke the handler, which logs and invokes the target method on the Calculator
InvocationHandler handler = new LoggingHandler(c);
//create a proxy
c = (Calculator) Proxy.newProxyInstance(c.getClass().getClassLoader(), c.getClass().getInterfaces(), handler);
}
return c;
}
}

Finally the test class:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class TestProxy {
public static void main(String[] args) {
System.out.println(“==============Without dynamic proxy=============”);
Calculator calc = CalculatorFactory.getInstance().getCalculator(false);
calc.add(3, 2);
System.out.println(“===============With dynamic proxy================”);
calc = CalculatorFactory.getInstance().getCalculator(true);
calc.add(3, 2);
}
}

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.