This post explains how to create proxy objects using Java Proxy api. We need the below items to create a proxy.
1) proxy interfaces (list of interfaces the dynamic proxy class will implement).
2) dynamic proxy class is proxy class generated at runtime and implements the proxy interfaces.
3) proxy instance is an instance of dynamic proxy class.
5) every proxy instance should have instance of InvocationHandler.
6) proxied object is the actual object for which proxy is created. The proxied object will also implement the proxy interfaces.
6) InvocationHandler is the class which has a reference to actual object and where we will write our custom logic that will be executed before or after or both before and after actual object’s method call.
Every call on proxy instance pass through InvocationHandler’s invoke method. The invoke method receives the below three parameters
1) proxy instance on which the method is called
2) The method object
3) Arguments that are to be passed to the method object.
The below example explains proxy creation
Proxy Interface
package reflect;
public interface Response {
public void response() throws Exception;
}
Actual Objects
package reflect;
public class ResponseImpl1 implements Response {
@Override
public void response() throws Exception {
System.out.println("ResponseImpl1 has responded.");
Thread.sleep(1000);
}
}
package reflect;
public class ResponseImpl2 implements Response {
@Override
public void response() throws Exception {
System.out.println("ResponseImpl2 has responded.");
Thread.sleep(5000);
}
}
InvocationHandler
package reflect;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class PerformanceMonitorInterceptor implements InvocationHandler {
private Object response;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long startTime = System.currentTimeMillis();
System.out.println("Start Time: " + startTime);
Object result = method.invoke(response, args);
long endTime = System.currentTimeMillis();
System.out.println("End Time: " + endTime);
long totalTime = endTime - startTime;
System.out.println("Total time taken: " + totalTime);
return result;
}
public Object getResponse() {
return response;
}
public void setResponse(Object response) {
this.response = response;
}
}
Main class
package reflect;
import java.lang.reflect.Proxy;
public class ProxyDemo1 {
public static void main(String[] args) throws Exception {
ResponseImpl1 responseImpl1 = new ResponseImpl1();
ResponseImpl2 responseImpl2 = new ResponseImpl2();
Class[] classes = {Response.class};
PerformanceMonitorInterceptor performanceMonitorInterceptor = new PerformanceMonitorInterceptor();
performanceMonitorInterceptor.setResponse(responseImpl1);
Response response1 = (Response)Proxy.newProxyInstance(ProxyDemo1.class.getClassLoader(), classes, performanceMonitorInterceptor);
response1.response();
System.out.println("Is response1 a proxy object: " + Proxy.isProxyClass(response1.getClass()));
performanceMonitorInterceptor.setResponse(responseImpl2);
Response response2 = (Response)Proxy.newProxyInstance(ProxyDemo1.class.getClassLoader(), classes, performanceMonitorInterceptor);
response2.response();
System.out.println("Is response2 a proxy object: " + Proxy.isProxyClass(response2.getClass()));
}
}
Explanation
As shown in above main code, PerformanceMonitorInterceptor is the InvocationHandler. The actual object to be proxied is set to PerformanceMonitorInterceptor using the setter method
performanceMonitorInterceptor.setResponse(responseImpl1);
classes array variable contains Response interface.
Class[] classes = {Response.class};
Proxy object is created using the below code
Response response1 = (Response)Proxy.newProxyInstance(ProxyDemo1.class.getClassLoader(), classes, performanceMonitorInterceptor);
newProxyInstance is static method in Proxy class. To this method we pass the class loader which will generate the proxy class, list of interfaces, and an instance of InvocationHandler.
This method
1) uses the class loader to generate dynamic proxy class implementing the list of interfaces
2) create a proxy instance
3) associate the proxy instance with instance of InvocationHandler
Output
Start Time: 1463946847085
ResponseImpl1 has responded.
End Time: 1463946848087
Total time taken: 1002
Is response1 a proxy object: true
Start Time: 1463946848089
ResponseImpl2 has responded.
End Time: 1463946853090
Total time taken: 5001
Is response2 a proxy object: true