Friday, February 12, 2010

Spring AOP: Dynamic Proxies vs. CGLib proxies

This article is from Jörg Heinicke’s blog.

Spring's AOP is proxy-based. Spring provides two different optionsto create the proxies. One is based on JDK dynamic proxies and works with interfaces, the other one utilizes CGLib and is based on classes. (That's why the property is called proxyTargetClassrespectively proxy-target-class.) For the moment I just want to provide a quick summary on the pros and cons of both options:
JDK dynamic proxies:

  • The class has to implement interfaces. Otherwise you will get ClassCastExceptions saying that $Proxy0 can not be casted to the particular class.
  • Eventually dynamic proxies force you to program to interfaces since you can not cast the proxy to the class - a feature Ireally like about them.
CGLib proxies:
  • The proxies are created by sub-classing the actual class. This means wherever an instance of the class is used it is also possible to use the CGLib proxy.
  • The class needs to provide a default constructor, i.e. without any arguments. Otherwise you'll get an IllegalArgumentException: "Superclass has no null constructors but no arguments were given." This makes constructor injection impossible.
  • The proxying does not work with final methods since the proxy sub class can not override the class' implementation.
  • The CGLib proxy is final, so proxying a proxy does not work. You will get an IllegalArgumentException saying "Cannot subclass final class $Proxy0". But this feature is usually not needed anyway. (This issue might be solved in the future.)
  • Since two objects are created (the instance of the class and the proxy as instance of a sub class) the constructor is called twice. In general this should not matter. I consider changing the class' state based on constructor calls a code smell anyway.
  • You have CGLib as additional dependency.
Both options suffer from some issues (not really issues, but you have to be aware of them):
  • Most important proxy-based AOP only works from "outside". Internal method calls are never intercepted.
  • Second, the object has to be managed by the Spring container. Instantiating it yourself using new does not work.
  • The proxies are not Serializable.
Regarding performance of the one or the other method I have read different things. I remember having read a blog post about CGLib proxies being better, one of the comments says dynamic proxies are. Actually the Spring reference has a paragraph on this itself:
There's little performance difference between CGLIB proxying and dynamic proxies. As of Spring 1.0, dynamic proxies are slightly faster. However, this may change in the future. Performance should not be a decisive consideration in this case.

I emphasized the last sentence by intention.
Especially for enforcing programming to interfaces and allowing constructor injection I strongly prefer the JDK dynamic proxies.

No comments:

Post a Comment