Spring Рекомендации АОП по аннотированным контроллерам
Я пытаюсь использовать AOP для выполнения некоторой обработки после аннотированного контроллера. Все работает без ошибок, но совет не выполняется.
Вот код контроллера:
@Controller
public class HomeController {
@RequestMapping("/home.fo")
public String home(ModelMap model) {
model = new ModelMap();
return "home";
}
}
и настройка в приложении-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>
и фактический совет
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!");
}
}
Можно ли даже иметь рекомендации по аннотированным контроллерам? Я использую Spring 2.5.
Ответы
Ответ 1
Возможно иметь совет по аннотированным контроллерам.
Я предполагаю, что вы хотите посоветоваться после выполнения всех методов в классах, аннотированных с помощью @Controller
.
Вот пример:
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..");
}
}
Если вы хотите использовать Spring AOP с синтаксисом AspectJ, вам также нужен файл конфигурации, например:
<?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>
Примечание. При использовании Spring AOP контейнер Spring будет только переплетать Spring beans. Если объект @Controller
не является Spring bean, вы должны использовать плетение AspectJ.
Ответ 2
У меня была та же проблема, что и рекомендации для Repository, но рекомендаций для контроллера не было. Наконец я нашел решение. Короче говоря, вам нужно убедиться, что ваше определение AOP загружено в контексте сервлета, а не в другом контексте.
В моем случае мое определение Spring AOP определено в tools-config.xml
. После перемещения отсюда
<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>
здесь,
<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>
Совет для контроллера работает.
Ответ 3
Для MVC-контроллеров предпочтительным методом достижения того, что вы пытаетесь сделать, является использование перехватчиков. См. http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-handlermapping-interceptor