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 I really 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.