
AOP Configuration
AOP Configuration
The Spring AOP support has been heavily customized for performance reasons.
One of the biggest differences between our aop facilities and Spring's default one is, our aop advice can only apply to "Service" beans, the logic is implemented in ServiceBeanAutoProxyCreator
and configured in base-spring.xml
<bean class="com.liferay.portal.spring.aop.ServiceBeanAutoProxyCreator">
<property name="methodInterceptor" ref="serviceAdvice" />
</bean>
This may sound like a huge limitation at beginning, but considering all liferay's aop logic is around service, we are not losing any function, instead we can get some performance gain by simplifying the mapping logic.
On the other hand, you can still use whatever Spring offers for AOP, just it won't scale well as what we provide. We are not rejecting the well known Spring AOP configuration style, we just provide a better simplied version for ourselves. If you are developing for core product, you'd better follow the pattern inside base-spring.xml for consistency. If you are working on customer projects and AOP performance is not your primary concern, you can keep using what you feel comfortable with.
ServiceBeanAutoProxyCreator defines an entry point of Liferay AOP chain, the chain is formed by a list of ChainableMethodAdvice
which technically just a MethodInterceptor
.
You need to give ServiceBeanAutoProxyCreator the first element in the aop chain, by default it is serviceAdvice, which in turn referring the next element, just like a linked list.
If you are creating a new AOP advice, you can extend AnnotationChainableMethodAdvice
or ChainableMethodAdvice
, depends on whether it is picking up pointcut by annotation. Then wire it in base-spring.xml at a proper position into the linked list.
The biggest AOP performance improvement comes from the runtime unplugging feature ChainableMethodAdvice provides. Which means, at runtime, if you can figure out that an AOP advice will never care a certain service method call, it can be completely unplug from call stack after the first call. So only the first time that you call a service method all aop advices run, after the first call, all unneeded aop advices for this service method are unplugged, since the second visit, you are only running through the necessary advices to avoid unnecessary aop mapping and call stack overhead.
AnnotationChainableMethodAdvice automatically unplugs itself if the target service method does not have the interested annotation, so you don't even need to worry about the unplugging logic. However if your advice is not annotation based, you will have to unplug it manually on a proper condition, you can see PACLAdvice
as an example, look for usage of com.liferay.portal.spring.aop.ServiceBeanAopCacheManager.removeMethodInterceptor(MethodInvocation, MethodInterceptor)