15 December, 2007

Spring AOP: Dynamic Proxies vs. CGLib proxies

Spring's AOP is proxy-based. Spring provides two different options to 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 proxyTargetClass respectively 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 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.


Raptor T Wiked said...

I beg to differ on your point that CGLib proxies are faster than Java dynamic proxies. In my personal experience, CGLib proxies perform slower.
This has been confirmed by several people on the net as well.

Marten Deinum said...

Joerg, great post summing up the differences. Can we link this page as default with proxy questions ;-).

joerg20 said...

Thanks Marten. Of course we can. This would increase our spare time a lot :-)

Raptor, thanks for your comment. Personally I do not really care about the performance difference. I never tested it myself but only got from something I read somewhere ;-) Now that I stumbled upon a paragraph in the reference I updated the post.

al0 said...

Concerning performance comparision - it highly depends on JDK version. Prior to JDK 1.4.2 dynamic proxies were noticeable slower, starting from 1.4.2 - marginally faster then CGLIB-based proxies. Hibernate JIRA contains some interesting discussion on this matter.

But there is much more important issue omitted from discussion. IT was not mentioned, that whole proxy-based AOP (CGLIB or not) does not cover objects intantiated not by Spring but directly in code with new(). While it seems to be absolutely obvious, it is major cause of confusions and questions in forums just next to "in-object" calls.

joerg20 said...

Thanks Oleksandr. Since there are no serious performance issues with the one or the other method I don't consider performance as a decisive criterion. That's why I never really cared about performance. First I want to have a good design, then I start to make compromises if it is necessary ;-)

Also originally this post was really intended as comparison between dynamic proxies and CGLib proxies and not so much about Spring's AOP in general. Since I added the other common issues I should probably have added this point as well. I'm going to update the post. Though I have to admit it is really too obvious to me :-)

Diego Plentz said...

"I consider changing the class' state based on constructor calls a code smell anyway."

Constructors are particularly useful to do dependency injection, so, no code smell to me :)

joerg20 said...

Diego, that's not what I meant. As a side note, I also prefer constructor injection over setter injection.

With the class' state I mean static variables like instance counters. Only for those it would be problematic if the constructor is called twice, once for the proxy and once for the wrapped object.

Miguel said...

Hello Joerg.
I'm working with a spring-struts application where jdk proxies are working fine, but I have a new requeriment that leads me to proxy Struts Actions classes.
By now, they aren't interfaced, and of course, jdk proxy doesn't work with.
So, I have three options.
- Modify everything to work with cglib2.
- Generate interfaces for Actions.
- Work with both proxies. ¿Is it possible to work with on spring?
It would be great if we could combine them, but I think that if possible it must attempt to application performance. Isn't it?

joerg20 said...

Hi Miguel,

Sorry for replying that late. I was very busy lately. On your issue:

I don't know your exact requirement but proxying Action classes sounds a bit awkward. What functionality has to be implemented on that level? Have you thought about introducing an additional layer below your Action classes and moving the functionality over there? This approach might be more reusable.

Extracting an interface from Struts' Action class and letting your Actions implement this should be a very simple solution. The techniques you use should rather adopt to the application than the other way around. Also, using CGLib and Dynamic Proxies in parallel should be no problem. Just make sure you don't proxy an instance multiple times. Just by using both approaches in parallel there should be no performance issue.

Miguel said...

Hello Joerg.

I have solved my problem without proxying twice. Avoiding that I'll explain which was the problem and which solution I applied. Anyway, I'd know if cglib and jdk proxies could work together -without taking care of awkwardness :)-

Introduce yourself telling you that I'm developing a framework for my application that stands on another one that I can't modify.

Their framework force us to work with spring-jdbc, and we have developed our own ORM with jdk proxies that emulates hibernate.

Those proxies work for Business Objects.

Ok. In another way, we have developed an StateMachineFilter that gets a request parameter called "flowPID", and if this parameter is present we do flowable actions (start actions - chain.doFilter - end actions).

But we found the problem that struts redirections work within the same http request, so, the filter wraps both actions and end action were executed later than expected.

I thought that proxing actions could be a solution ¿couldn't it?, but I decided to manage it by setting the active flowPID in the application context and creating an Aspect (AOP) over Facade calls, cause we assume that there's only one business call on each action.

Many thanks Joerg.

vishal thakur said...

thanks Joerg.you helped me to solve the problem regarding proxy