Spring JDK Proxy vs CGLIB, thoughts, curses and the enlightment.

Spring is an amazing framework which provides lots of cool features that solve very complex problems for you. In doing so a lot of these features such as caching, aspect logging, DB/orm heavily rely upon Spring AOP framework.

What does that actually mean? Well in short withing context of Spring framework it means that when application context start up it will create a bunch of proxies that wrap around your means to track method invocations and hence apply special codes before and/or after these methods are executed. Examples would be: cache look up, openning/comitting transactions and so on.

This is very cool stuff and what is amazing is that you (in theory) never need to worry about it - it just works.

... or is it? ...

Well it is all fine when you do hello world application and do a POC for you ORM layer or Logging or caching but then when you come to implementation of a very complex enterprise application all these proxies start to overlap, wrap proxies over proxies and do a lot of crazy stuff that basically forces you to dig deep into Spring in search of answers.

So the point is ... (this is the curses part which I shall skip) ...

Now to the enlightment. This is a quick and easy to understand explanation how this whole AOP this really works and what you should watch out for.

1. What proxies Spring uses?

There are two types of proxies available:

JDK proxy, which is comes out of the box in JDK and CGLib, which is created by the CGLib library (3rd party dependency).

JDK Proxy only works with beans that implement an interface (which in my view is a good thing, you should code to intreface not concrete classes) and it is also the Spring recommended way of using AOP.

Quote from Spring doc:

As it is good practice to program to interfaces rather than classes, business classes normally will implement one or more business interfaces.

However, there are lots of people out there who like to code concrete classes and therefore must use CGLib. This means that there should be a cglib.jar on classpath to make it work and there is also a side effect whereby your proxy constructors will run twice - so use constructors only for dependency injection (no business logic allowed)

2. How does spring AOP knows what proxy to use?

Configuration mostly come from <aop:config/>, <tx:annotation-driven/>, <aop:aspectj-autoproxy/> and <aop:scoped-proxy/> as well as some configurable properties on some factory beans.

The important thing to remember is that some of these configs are merged before being processed.

Quote from Spring doc:

Multiple <aop:config/> sections are collapsed into a single unified auto-proxy creator at runtime, which applies the strongest proxy settings that any of the <aop:config/> sections (typically from different XML bean definition files) specified. This also applies to the <tx:annotation-driven/> and <aop:aspectj-autoproxy/> elements.
To be clear: using ' proxy-target-class="true"' on <tx:annotation-driven/>, <aop:aspectj-autoproxy/> or <aop:config/> elements will force the use of CGLIB proxies for all three of them.

So be careful when defining these tags in multiple xml configuration files.

Now in order to enforce JDK proxy the following configuration must be used: <aop:config proxy-target-class="false">

Example:

    
        
...
    

 

Make sure that all of config tags have the proxy-target-class set to false. However this does not affect the TransactionProxyFactoryBean (if you are using ORM)

In order to use JDK proxies for your transactional beans you must set proxyTargetClass property to false.

Example:

    
        
            NOTE: see org.springframework.transaction.TransactionDefinition

            disable transactions by default (bean must explicitly specify)
        
        
        
        
            
                PROPAGATION_NOT_SUPPORTED
            
        
    

For CGlib the corresponding proxyTargetClass and proxy-target-class should be set to true.

As you may have noticed I use XML configuration for Spring and some people may find it ancient approach suitable only for those who like the Flinstones. However, my view is that annotations polute your code because they are directly applied to your classes. Image if you use Spring annotations, The some JPA, then some JAXB then some other 3rd party libraries annotation - it is a complete mess! With XML you create POJO's and then define separate XML configurations for your application concerns like: ORM, DTO, Spring, cache and so on. Moreover each of these confiurations can be changes without touching the code. So I think it is much better from the SOLID point of view. (and yes I did enjoy the Flinstones, so there). But if you are a big fan of annotations I am sure you can google for the corresponding configs.

3. Now that you now everything - or do you?

Now you may think that you know everything and you got your app working like you want - think again! In what order do your aspects execute?

Yes, if you have transactions and then ehcache and then some performance logging you may have several proxies! So you need to order them so that you know precisely when and if your aspects get executed. Use the order attribute.

Example:

    
        
...
    

 

So now hopefully you get the bigger picture of how AOP works in Spring and major gotchas that you may encounter.

Let me know if you think that more usefull information could be added or you had some interesting use case and a magical solution for it )

 

 

This page was last updated on: 11/04/2014 12:47