JDK Dynamic Proxies

In this article we will cover JDK Dynamic Proxies along with their contribution to the Aspect Oriented Programming paradigm

Introduction

JDK Dynamic Proxies allow one to create implementations of Java interfaces at runtime by the means of Reflection. A proxy may be seen as a subject that will forward method calls to target instances and eventually return any result produced by the target instance to the caller. Since the invocation chain will pass through the proxy, the proxy itself will also be able to do arbitrary processing before and after the target method invocation. The aforementioned proxy features should make us conclude that proxies may be used to implement several design patterns, for example the Proxy, Facade and Decorator patterns. One of the main paradigms of Aspect Oriented Programming (AOP) is the separation of cross cutting concerns from business logic. Code that implement concerns like transaction management, logging or validation (among many others) should not reside within classes that implement business logic itself. So it is natural that frameworks that make heavy usage of AOP will absolutely rely on proxying mechanism. The very popular Spring Framework uses JDK Dynamic Proxies as one of its proxy creation strategies. When we declare a Transactional method inside a Spring service, the container will create a proxy that will intercept calls to the target method and decorate it with the required transaction management instructions.

The JDK Dynamic Proxy

We start by creating a simple business interface and an illustrative implementation: ServiceOne public interface ServiceOne { String sayHello(); }



ServiceOneBean public class ServiceOneBean implements ServiceOne { @Override public String sayHello() { System.out.println("Executing method sayHello"); return "Hello"; } } In this article we will create a proxy that logs method execution times. For this we may define a proxy like the following: LogExecutionTimeProxy import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class LogExecutionTimeProxy implements InvocationHandler { // The target instance private Object invocationTarget; public LogExecutionTimeProxy(Object invocationTarget) { this.invocationTarget = invocationTarget; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // Start time long startTime = System.nanoTime(); // Invoke the method on the target instance Object result = method.invoke(invocationTarget, args); // Print the execution time System.out.println("Executed method " + method.getName() + " in " + (System.nanoTime() - startTime) + " nanoseconds"); // Return the result to the caller return result; } } A dynamic proxy must implement the InvocationHandler interface. This interface has a single method - invoke() - that will be used to forward methods to an arbitrary target instance. One may decorate the method interception with any code required. In the presented case we are logging the target instance method execution time. We may now use our just defined dynamic proxy: Dynamic Proxy usage import java.lang.reflect.Proxy; public class Main { public static void main(String args[]) { // Create the target instance ServiceOne serviceOne = new ServiceOneBean(); // Create the proxy ServiceOne proxy = (ServiceOne) Proxy.newProxyInstance(ServiceOne.class.getClassLoader(), serviceOne.getClass().getInterfaces(), new LogExecutionTimeProxy(serviceOne)); // Invoke the target instance method through the proxy String result = proxy.sayHello(); System.out.println("Result: " + result); } } The dynamic proxy instance is created through the Proxy.newProxyInstance() static method call. This method receives three arguments: The class loader that will be responsible for loading our proxy instance, the interfaces that our proxy will implement, and finally the user defined proxy (the one that implements the InvocationHandler interface). One should now conclude that a JDK Dynamic Proxy must implement at least a single interface. When we execute the above test method, the following output will be generated: Executing method sayHello

Executed method sayHello in 1447164 nanoseconds

Result: Hello

Relationship with AOP

The mechanism we have just seen is the basis for many Aspect Oriented Programming frameworks. This is one of the ways that Spring uses to wire cross cutting concerns to our declared Spring beans. Spring will use the annotation based configuration (or XML configuration) in order to understand which concerns must be wired to the existing Spring beans and create the respective proxies. The proxies will then be injected into client instances providing a subtle way of hiding all cross cutting details from the business implementation.

Curiosity about Java 8

Since InvocationHandler interface is a single method interface, it is considered as a functional interface (more information in Java 8 Lambda expressions and Java 8 Method References). We could have defined our proxy using a lambda expression: Dynamic Proxy using a lambda expression // Create the target instance ServiceOne serviceOne = new ServiceOneBean(); // Create the proxy ServiceOne serviceOneProxy = (ServiceOne) Proxy.newProxyInstance( ServiceOne.class.getClassLoader(), serviceOne.getClass() .getInterfaces(), (proxy, method, args) -> { // Start time long startTime = System.nanoTime(); // Invoke the method on the target instance Object result = method.invoke(serviceOne, args); // Print the execution time System.out.println("Executed method " + method.getName() + " in " + (System.nanoTime() - startTime) + " nanoseconds."); // Return the result to the caller return result; }); // Invoke the target instance method through the proxy serviceOneProxy.sayHello();

Reference

Related Articles

Comments