Aspectj static weaving: do the aop at compile time using Aspectj’s own compiler: ajc.
JDK Proxy: when class implements some interface. The proxy will implement every interface. It can NOT be cast to the original target class because it’s simply a dynamic proxy that happens to implement the same interface(s) as the target
CGLIB: When class is concrete without any interface. The proxy will subclass the target.
Note: the JDK-proxy and CGLIB is transparent to the user.
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”>
<aop:config proxy-target-class="false"> <aop:advisor advice-ref="runtimeCacheAdvice" pointcut="execution(* com..ErpRuntimeContextInternal.providePreferences(..))"> ... </aop:advisor></aop:config>
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.
<bean id="txSecurityProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <description> NOTE: see org.springframework.transaction.TransactionDefinition disable transactions by default (bean must explicitly specify) </description> <property name="transactionManager" ref="transactionManager"> <property name="proxyTargetClass" value="false"> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_NOT_SUPPORTED</prop> </props> </property> </property></property></bean>
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.
<aop:config proxy-target-class="false"> <aop:advisor advice-ref="runtimeCacheAdvice" order="100" pointcut="execution(* com..ErpRuntimeContextInternal.providePreferences(..))"> ... </aop:advisor></aop:config>
Another link about getting object behind the proxy.