Thursday, December 6, 2007

Spring AOP & Robotic Spiders

- Definition
# Advice
It contains the logic of your aspect. Also because Spring's jointPoint model is built around method interception. There are four types of advice types in Spring: Around, Before, After, Throws.

# PointCut
It defines where advices is woven into classes. It determines if a particular method on a particular class mataches a particular criterion. There are static and dynamic pointcut. Spring provides two static pointcuts: StaticMethodMatcherPointcut and RegexpMethodPointcut.

It seems a good practice to use annotation to identify the pointcuts and achieve a good balance between xml config and annotation, e.g.,
  public boolean matches(Method method, Class targetClass) {
     boolean isAnnotationPresent = method.isAnnotationPresent(Auditable.class);
    ...

# Advisor
It combine advice and pointcuts into one object. Most of Spring pointcuts have a corresponding pointcutAdvisor such as StaticMethodMatcherPointcutAdvisor.


public interface PointcutAdvisor {
  Pointcut getPointcut();
  Advice getAdvice();
}


- The ProxyFactoryBean class is a central class for explicitly creating proxied
objects within a BeanFactory. As demonstrated, you can give it an interface to
implement, a target object to proxy, and advice to weave in, and it will create a
brand-new proxied object. (dynamically create proxy class)


<bean id="kwikEMart" class="org.springframework.aop.framework.ProxyFactoryBean" >
   <property name="proxyInterfaces">
      <value>com.springinaction.chapter03.store.KwikEMart</value>
   </property>
   <property name="interceptorNames">
      <list><value>welcomeAdvice</value></list>
   </property>
   <property name="target"><ref bean="kwikEMartTarget"/>
   </property>
</bean>


The interceptorNames is the bean names of the advice to be applied to the target. It can be names of interceptors, advisors, or any other advice type.

The proxied objects will be created when it loads all of the beans from the BeanFactory on runtime. (aspect weaving could happen on compile time or class load time too which requires special compiler and classloader).
*** It is interesting to know that webwork (Struts2) interceptor uses different mechanism though they shares the same AOP concepts. It doesn't create proxy objects (classes) or modify byte code. It applies command pattern to decouple the caller and called action, ActionInvocation keeps a stack of interceptor, and it calls intercept() one by one until it reach the execute() of action instance. After result is return, the interceptors is invoked in reverse order. The magic exists in actionInvocation.invoke() which is a recursive call.

- Auto Proxy
For large application, it become cumbersome to explicitly create each proxy object using the ProxyFactoryBean. BeanNameAutoProxyCreator create proxies for beans that match a set of names. The more powerful autoproxy creator is the DefaultAdvisorAutoProxyCreator. The magic of it lies within its implementation of BeanPostProcessor interface. After you bean's definition have been read in by the ApplicationContext, the DefaultAdvisorAutoProxyCreator scours the context for any advisors. It then applied these advisors to any beans that match the advisor's pointcut. - It is like robotic spiders where unleashed to find Tom Cruise in Minority Report.


<bean id="performanceThreasholdInterceptor" ...>...</bean>
<bean id="advisor" class="...RegexpMethodPointcutAdvisor">
  <property name="advice">
    <bean class="performanceThresholdInterceptor"/>
</property>
  <property name="pattern">
    <value>.+Service\..+</value>
  </property>
</bean>
<bean id="autoProxyCreator" class=".....DefaultAdvisorAutoProxyCreator"/>

No comments: