I am trying to use AOP to do some processing after an annotated controller. Everything is running with no errors, but the advice is not being executed.
Here is the
It's possible to have advice on annotated controllers.
I assume you want to advice after execution of all methods in classes annotated with @Controller
.
Here's an example:
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class ControllerAspect {
@Pointcut("within(@org.springframework.stereotype.Controller *)")
public void controllerBean() {}
@Pointcut("execution(* *(..))")
public void methodPointcut() {}
@AfterReturning("controllerBean() && methodPointcut() ")
public void afterMethodInControllerClass() {
System.out.println("after advice..");
}
}
If you want to use Spring AOP with AspectJ syntax, you also need a configuration file like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="controllerAspect" class="controller.ControllerAspect" />
<aop:aspectj-autoproxy>
<aop:include name="controllerAspect" />
</aop:aspectj-autoproxy>
</beans>
Note: With Spring AOP, the Spring container will only weave Spring beans. If the @Controller
object isn't a Spring bean, you must use AspectJ weaving.
I had the same problem where advice for Repository was working, but advice for Controller was not. Finally I found a solution. In short, you need to make sure your AOP definition is loaded in Servlet context, not a different context.
In my case, my Spring AOP definition is defined in tools-config.xml
. After moving it from here
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/tools-config.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
to here,
<servlet>
<servlet-name>petclinic</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/mvc-core-config.xml, classpath:spring/tools-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
the advice for Controller is working.
For MVC controllers the preferred method of accomplishing what you are trying to do is to use interceptors. See http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-handlermapping-interceptor