Marat Asadurian Marat Asadurian - 4 months ago 18
Java Question

Ordering aspects with Spring AOP && MVC

I am trying to use Spring AOP with Spring MVC Controller.
I have 3 aspects, and want the to be in specific order. In order to do this, I use Ordered interface and implement getOrder method:

@Aspect
@Component
public class LoggingAspect implements Ordered{

public int getOrder() {
System.out.println("Abra");
return 1;
}


Adviced class:

@Component
@Controller
public class HomeController {


Pointcuts:

@Aspect
public class SystemArchitecture {

@Pointcut("execution (* com.jajah.StorageManager.HomeController.*(..))")
public void inHomeController(){}

@Pointcut("execution (* com.jajah.StorageManager.HomeController.*(..))")
public void loggable(){}

@Pointcut("execution (* com.jajah.StorageManager.HomeController.*(..))")
public void authenticated(){}

}


Configuration:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

<annotation-driven />
<context:annotation-config />
<aop:aspectj-autoproxy proxy-target-class="false"/>

<beans:bean id="AuthenticationAspect" class="com.jajah.CommonAspects.SecurityAspects.OAuthAspect"/>
<beans:bean id="ErrorHandlingAspect" class="com.jajah.StorageManager.Aspects.ErrorHandlingAspect"/>


<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />

<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<!-- <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />

</beans:bean> -->

<beans:bean name="homeController" class="com.jajah.StorageManager.HomeController">
<beans:constructor-arg>
<beans:ref bean="CloudStorage"/>
</beans:constructor-arg>
<beans:constructor-arg>
<beans:ref bean="ConfigurationContainer"/>
</beans:constructor-arg>
</beans:bean>

<beans:bean id="CloudStorage" name="CloudStorage" class="com.jajah.StorageManager.CloudStorageProxy" scope="singleton">
<beans:constructor-arg>
<beans:ref bean="ConfigurationContainer"/>
</beans:constructor-arg>
</beans:bean>

<beans:bean id ="ConfigurationContainer" class="com.jajah.StorageManager.ConfigurationContainer" scope="singleton"/>





</beans:beans>


The getOrder doesn't do the trick.
I will appreciate any practical advice, or if you don't have the exact answer I will appreciate any theoretical knowledge about the Spring Proxy and the weaving mechanism.

I will post any Code/Configuration required upon demand.
Thanks for reading.

Update:
1. I tried @Order(1) with same result.
2. I tried to move aspects to same package, it changed their order, but I still couldn't control it.

Answer

You don't need to implement Ordered interface.

In Spring AOP you can do things much easier.

@Aspect
@Order(1)
public class AspectA
{
  @Before("............")
   public void doit() {}
}

@Aspect
@Order(2)
public class AspectB
{
  @Before(".............")
  public void doit() {}
} 

Update:

@Aspect
@Order(1)
public class SpringAspect {

    @Pointcut("within(com.vanilla.service.MyService+)")
    public void businessLogicMethods(){}

     @Around("businessLogicMethods()")
     public Object profile(ProceedingJoinPoint pjp) throws Throwable {
             System.out.println("running Advice #1");   
         Object output = pjp.proceed();
         return output;
     }
}

@Aspect
@Order(2)
public class SpringAspect2 {

    @Pointcut("within(com.vanilla.service.MyService+)")
    public void businessLogicMethods(){}

     @Around("businessLogicMethods()")
     public Object profile(ProceedingJoinPoint pjp) throws Throwable {
             System.out.println("running Advice #2");   
         Object output = pjp.proceed();
         return output;
     }
}

Now the application Context Configuration XML:

<context:annotation-config />
<aop:aspectj-autoproxy />

  <bean id="springAspect" class="com.vanilla.aspect.SpringAspect" />
    <bean id="springAspect2" class="com.vanilla.aspect.SpringAspect2" />

You need to enable AOP proxy by:

<aop:aspectj-autoproxy />

otherwise no advice will be activated.

Update 2:

I just make a research on this issue. @order annotation works only on Spring's based proxy AOP (Which I'm using in my example). Accoridng to documentation if you are using weaving you should use declare precedence option.

Update 3

  1. I don't see any advices in your code, just aspects and pointcuts.
  2. If your Advice classes are: x.y.z.SystemArchitecture

then you need to configure it at as

<bean id="systemArchitecture" class="x.y.z.SystemArchitecture" /> 

and I don't see it in your code.

  1. "execution (* com.jajah.StorageManager.HomeController.*(..))" what are you targeting on? Can you write it using words?

Anyway. Please drop me a message on facebook and I'll send you working example which does exactly what are you trying to do.