Overview

A Java dynamic proxy class is a type of “add-on” on top of the original class, which allows the Java developers to change the behaviors of the original class as per requirement. Suppose, if you are using a class as part of an off-the-shelf JAR library and you cannot simply rewrite its source code but you also need to change how this class behaves.

For instance, you don’t know which method of this class might be called on your object, but you want to output an important “acknowledgment” message. Java Dynamic Proxies is the ideal solution for this problem.

In this article, we will learn all about Java dynamic proxies. What are the Java dynamic proxies? how do they work? and when you should be ideally using it in your Java code.

What is Java Dynamic Proxy?

Java Dynamic Proxies are part of the Java proxy design pattern. It allows the creation of proxy objects when a program requires to extend or modify some functionalities of an already existing class. In that case, A proxy object is instantiated instead of the original one. Commonly, the proxy objects have the same methods as the original object and the original class is extended in a Java proxy class. The Java dynamic proxies have a handle over the original objects and original class methods can also be called by that.

Due to this, the proxy classes can implement a lot of different things in a very convenient way, few examples of such things include:

  • A logging method can be extended to the original class to record when a method starts and stops.
  • Extra checks can be performed on arguments using Java dynamic proxies.
  • A proxy class can also be used to mock the behavior of the original class before finalization to check if it is performing as expected.

The above-mentioned applications cannot be done without modifying the original code of the class which makes them the ideal applications for Java dynamic proxies.

In such applications, the proxy class does not directly implement the functionality upon the original class objects. Following the single responsibility principle, the proxy class only creates a proxy and the actual behavior is modified in the handlers. When the proxy object is invoked instead of the original object, the Java dynamic proxies then decide whether if it has to invoke the original method or the handler. The handler may do its extended tasks and it can also call the original method to perform the original tasks as well.

Pre-requisites for using Java dynamic Proxies

It is a relatively advanced topic in Java Programming language because it requires some extensive knowledge of Java. The developers planning to work with Java dynamic proxies must know about the use of the reflection class or the bytecode manipulation or how to compile the Java code that is generated dynamically. To create the bytecode, you should learn how to use cglib or bytebuddy or the built-in Java compiler, first.

See Also: Java Scanner – Comprehensive Guide with Examples

What is InvocationHandler?

InvocationHandler is a special interface that allows us to intercept any method call to the object and add the additional behavior that we need. We first need to create our interceptor by creating a class that implements this interface. It only contains one method: invoke(), in which the original object is passed as an argument, to be proxied.

When we think about the proxy classes and the handlers that are invoked by them, it is understood that why the separation of responsibilities is very important here. The proxy class is always generated during the run-time, but the handler invoked by the proxy class can be coded with the source code and it can be compiled along with the code of the whole program during compile time.

How to use Java dynamic proxies in your Code?

Proxy classes, as well as instances of them, are created using a static method of the class java.lang.reflect.Proxy. It is part of the JDK and can create a proxy class or directly an instance of it. The use of the Java built-in proxy is relatively easier. All you need to do is implement a java.lang.InvocationHandler, so that the proxy objects can later invoke it. After this, the invoke() method from Invocation Handler is called.

Another method, the Proxy.getProxyClass method returns the java.lang.Class object for a proxy class given a class loader and an array of interfaces.

According to the Dynamic Proxy classes Java documentation, there are some restrictions on the parameters that must be passed to Proxy.getProxyClass:

  • All of the Class objects in the interfaces array must represent interfaces, not classes or primitive types.
  • Two elements in the interfaces array must not refer to identical Class objects.
  • All the interface types must be visible by name through the specified class loader.
  • All non-public interfaces must be in the same package; or else, it will not be possible for the proxy class to implement all of the interfaces, regardless of whatever package it is defined in.
  • For any number of member methods of specified interfaces that have the same signature:
    • If the return type of any method is void or a primitive type, then all of the methods must have that same return type.
    • If not then, one of the methods must have a return type that can be assigned to all of the return types of all the methods.
  • The resulting proxy class must not exceed any limits imposed on classes by the virtual machine.

This code below demonstrates all the discussed points to use of Java Dynamic proxies in your code:

1.  package proxy;
2.
3.  import java.lang.reflect.InvocationHandler;
4.  import java.lang.reflect.InvocationTargetException;
5.  import java.lang.reflect.Method;
6.  import java.lang.reflect.Proxy;
7.
8.  public class ProxyDemo {
9.
10.     interface If {
11.         void originalMethod(String str);
12.     }
13.
14.     static class Original implements If {
15.         public void originalMethod(String str) {
16.             System.out.println(str);
17.         }
18.     }
19.
20.     static class Handler implements InvocationHandler {
21.         private final If original;
22.
23.         public Handler(If original) {
24.             this.original = original;
25.         }
26.
27.         public Object invoke(Object proxy, Method method, Object[] args)
28.                 throws IllegalAccessException, IllegalArgumentException,
29.                 InvocationTargetException {
30.             System.out.println("Before the proxy: ");
31.             method.invoke(original, args);
32.             System.out.println("After the proxy: ");
33.             return null;
34.         }
35.     }
36.
37.     public static void main(String[] args){
38.         Original original = new Original();
39.         Handler handler = new Handler(original);
40.         If a = (If) Proxy.newProxyInstance(If.class.getClassLoader(),
41.                 new Class[] { If.class },
42.                 handler);
43.         a.originalMethod("Hello");
44.     }
45.
46. }
47.

 

Now, if the handler wants to invoke the original method on the original object, first, it must have the access to it. This will not be provided by the Java proxy implementation. The developer has to pass this argument to the handler instance manually in the code.

Proxy Object

You must have noted that an object often named “proxy” is passed as an argument to the invocation handler. This is the proxy object that is generated by the Java reflection dynamically and not the object we want to proxy. Due to this, developers use a separate handler object for each original class or they can also use some shared object that knows which original object is to be invoked if there is any method to invoke at all. You can also create an invocation handler and a proxy of an interface that does not have any original object. You don’t need any class to implement the interface in the code. The dynamically created proxy class will implement the interface automatically.

Java Dynamic Proxies Practical Applications

The Java dynamic proxies are actively used in popular technologies. One of the common usages is seen in security frameworks.

  • It is used to add security checks in all the methods that are supposed to be used by authorized personnel. Using the Java dynamic proxies, a security check can be added resulting in the user entering valid credentials without duplicating the verification code to access each method.
  • It can also be used to create a log for a method. This is also easily doable by using a proxy class. You could simply add additional code to the original methods to display the complete log at the end.

Conclusion

We have covered all the basics of the Java dynamic proxy. It is a quite functional yet very intricate tool for a Java developer but if used correctly it can be a fine addition to your java toolkit.

Author

Shaharyar Lalani is a developer with a strong interest in business analysis, project management, and UX design. He writes and teaches extensively on themes current in the world of web and app development, especially in Java technology.

Write A Comment