Search code examples
javadesign-patternsproxydynamic-proxyuse-case

Usefulness of java dynamic proxies vs regular proxies


I need some advice to which scenarios a dynamic proxy would prove more useful than a regular proxy.

I've put alot of effort into learning how to use dynamic proxies effectively. In this question, set aside that frameworks like AspectJ can perform basically everything we try to achieve with dynamic proxies, or that e.g., CGLIB can be used to address some of the shortcomings of dynamic proxies.

Use cases

  • Decorators - e.g., perform logging on method invocation, or cache return values of complex operations
  • Uphold contract - That is, making sure parameters are within accepted range and return types conform to accepted values.
  • Adapter - Saw some clever article somewhere describing how this is useful. I rarely come across this design pattern though.

Are the others?

Dynamic proxy advantages

  • Decorator: Log all method invocations, e.g.,

public Object invoke(Object target, Method method, Object[] arguments) {
         System.out.println("before method " + method.getName());
         return method.invoke(obj, args);
     }
}

The decorator pattern is definately useful as it allows side effects to all proxies methods (although this behaviour is a book-example of using aspects ..).

  • Contract: In contrast to a regular proxy, we need not implement the full interface. E.g.,

public Object invoke(Object target, Method method, Object[] arguments) {
     if ("getValues".equals(method.getName()) {
         // check or transform parameters and/or return types, e.g., 
         return RangeUtils.validateResponse( method.invoke(obj, args) );
     }

     if ("getVersion".equals(method.getName()) {
         // another example with no delegation
         return 3;
     }
} 

The contract on the other hand only gives the benefit of avoiding the need to implement a complete interface. Then again, refactoring proxied methods would silently invalidate the dynamic proxy.

Conclusion

So what I see here is one real use case, and one questionable use case. What's your opinion?


Solution

  • There are a number of potential uses for dynamic proxies beyond what you've described -

    1. Event publishing - on method x(), transparently call y() or send message z.
    2. Transaction management (for db connections or other transactional ops)
    3. Thread management - thread out expensive operations transparently.
    4. Performance tracking - timing operations checked by a CountdownLatch, for example.
    5. Connection management - thinking of APIs like Salesforce's Enterprise API that require clients of their service to start a session before executing any operations.
    6. Changing method parameters - in case you want to pass default values for nulls, if that's your sort of thing.

    Those are just a few options in addition to validation and logging like you've described above. FWIW, JSR 303, a bean validation specification, has an AOP-style implementation in Hibernate Validator, so you don't need to implement it for your data objects specifically. Spring framework also has validation built in and has really nice integration with AspectJ for some of the stuff described here.