Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring AOP Advice on Annotated Controllers

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 controller code:

@Controller
public class HomeController {       
    @RequestMapping("/home.fo")
    public String home(ModelMap model) {
        model = new ModelMap();
        return "home";
    }   
}

and the setup in application-config

<aop:aspectj-autoproxy/>

<bean id="testAdvice" class="com.test.TestAdvice">
</bean>

<bean id="testAdvisor"
    class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">
    <property name="advice" ref="testAdvice" />
    <property name="expression" value="execution(* *.home(..))" />
</bean>

and the actual advice

public class TestAdvice implements AfterReturningAdvice {

    protected final Log logger = LogFactory.getLog(getClass());

    public void afterReturning(Object returnValue, Method method, Object[] args,
            Object target) throws Throwable {
        logger.info("Called after returning advice!");
    }
}

Is it even possible to have advice on annotated controllers? I am using Spring 2.5.

like image 941
jdana Avatar asked Jul 22 '10 14:07

jdana


People also ask

Which annotations are used to declare advice in Spring AOP?

We can use @Before annotation to mark an advice type as Before advice. After (finally) Advice: An advice that gets executed after the join point method finishes executing, whether normally or by throwing an exception. We can create after advice using @After annotation.

Which list of five advice type is correct in Spring AOP?

There are five types of advices in the Spring AOP framework: before, after, after-returning, after-throwing, and around advice. Advices are taken for a particular join point. We will discuss these advices further in this section. Target object: An object on which advices are applied, is called the target object.

What is aspect advice PointCut Joinpoint and advice arguments in AOP?

An important term in AOP is advice. It is the action taken by an aspect at a particular join-point. Joinpoint is a point of execution of the program, such as executing a method or handling an exception. In Spring AOP, a joinpoint always represents a method execution.


2 Answers

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.

like image 161
Espen Avatar answered Oct 18 '22 22:10

Espen


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.

like image 26
xli Avatar answered Oct 18 '22 22:10

xli