Showing posts with label Spring. Show all posts
Showing posts with label Spring. Show all posts

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.

07 August, 2007

1,000th post

Nothing that really matters to the general public I guess. But I made my 1,000th post yesterday in the Spring forums. At the moment it's the community I'm most active in after I worked with Spring on my last two major projects.

The first project was a major refactoring. The web application was mainly separated into a web tier based on Apache Cocoon and a business tier without a container or distinct architecture. I introduced Spring for the dependency injection in the business tier and replaced the home-grown transaction framework with a JTA-based solution. Besides the database we access a Corba server and the file system transactionally so we need distributed transactions and two-phase commits. I wrote an XAResource/ JCA implementation for Apache Commons Transaction. Unfortunately I can't release this stuff as open-source but have to reimplement it when the time allows it. I use Jencks which integrates the Apache Geronimo transaction and connection management, so I don't need a full-blown JEE server, but I can use Spring and Apache Tomcat.

The second project was a portal. Starting from scratch was really nice. I could reuse my JTA/ JCA stuff and added JMS to the picture. As portal server Liferay 4.1.2 was chosen - and I learned to hate it quite fast. So many issues especially (but not only) with IBM DB2. Lately I switched to 4.3.0 - and I am quite happy with it. They have improved tremendously and now I can also recommend it. For the portlets I used Spring Portlet MVC which was really new at that time and had still the one or the other issue. But in contrary to Liferay (this improved a lot as well) and especially Hibernate (that's a topic on its own) I really got help from the community and issues got fixed really fast. That's when it makes fun to live on the bleeding edge and is not only frustrating.

Getting more and more used to the different parts of Spring I also started to share my knowledge. First it have been the custom scopes (which I used in both projects) and proxying (mostly for declarative transactions), later I added Spring MVC in general, Spring Portlet MVC in particular and the PropertyEditors to the picture. And so that's what I focus mainly on in the Spring forums.

Actually my home community is Apache Cocoon. That's were I started in end of 2000 and I became a committer in mid 2003. Unfortunately, by not working really with Cocoon for the last two years I lost more or less track of its development. I still try to bring me in from time to time though (as lately by propagating PropertyEditors as in Spring ;-) ). I'd like to work more again in this community again in the future, especially with the forthcoming next version 2.2.