【问题标题】:implement AOP for Controllers in Spring 3在 Spring 3 中为控制器实现 AOP
【发布时间】:2012-05-15 09:03:17
【问题描述】:

如何使用带注释的控制器实现 AOP?

我已经搜索并找到了关于该问题的两个先前帖子,但似乎无法使解决方案发挥作用。

posted solution 1

posted solution 2

这是我所拥有的:

调度 Servlet:

<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="
            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/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <context:annotation-config/>
    <context:component-scan base-package="com.foo.controller"/>

    <bean id="fooAspect" class="com.foo.aop.FooAspect" />

    <aop:aspectj-autoproxy>
        <aop:include name="fooAspect" />
    </aop:aspectj-autoproxy>
</beans>

控制器:

@Controller
public class FooController {

    @RequestMapping(value="/index.htm", method=RequestMethod.GET)
    public String showIndex(Model model){
        return "index";
    }
}

方面:

@Aspect
public class FooAspect {

    @Pointcut("@target(org.springframework.stereotype.Controller)")
    public void controllerPointcutter() {}

    @Pointcut("execution(* *(..))")
    public void methodPointcutter() {}

    @Before("controllerPointcutter()")
    public void beforeMethodInController(JoinPoint jp){
        System.out.println("### before controller call...");
    }

    @AfterReturning("controllerPointcutter() && methodPointcutter() ")
    public void afterMethodInController(JoinPoin jp) {
        System.out.println("### after returning...");
    }

    @Before("methodPointcutter()")
    public void beforeAnyMethod(JoinPoint jp){
        System.out.println("### before any call...");
    }
}

beforeAnyMethod() 适用于不在控制器中的方法;在对控制器的调用中,我无法执行任何操作。我错过了什么吗?

【问题讨论】:

    标签: spring controller aop


    【解决方案1】:

    为了在 Spring 3.1 中使用 @Controller 注释的类中的 HandlerMethod 上放置方面,您需要在 aspectj-autoproxy 元素上具有 proxy-target-class="true" 属性。您还需要将 CGLIB 和 ASM 库作为 WAR/EAR 文件中的依赖项。您可以将带注释的方面类指定为 bean 并使用上述 aop:include,也可以将 aop:include 保留在外,并在组件扫描元素中添加类似的过滤器:

    <context:component-scan>
      <context:include-filter type="aspectj"
        expression="com.your.aspect.class.Here"/>
    </context:component-scan>
    

    我不知道这是否只是 Spring 3.1 的要求,但我知道如果没有这个,您将无法在控制器 HandlerMethod 上放置方面。您会收到类似于以下内容的错误:

    Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class
    HandlerMethod details: 
    Controller [$Proxy82]
    Method [public void com.test.TestController.testMethod(java.security.Principal,javax.servlet.http.HttpServletResponse) throws javax.servlet.ServletException]
    Resolved arguments: 
    [0] [null] 
    [1] [type=com.ibm.ws.webcontainer.srt.SRTServletResponse] [value=com.ibm.ws.webcontainer.srt.SRTServletResponse@dcd0dcd]
    

    如果您的切面位于非控制器类中的方法上,则不需要这样做

    【讨论】:

    • Myy应用上下文如下applicationContext.xml有2个Aspect Java类,LogControllerAspect和LogDAOAspect。 LogDAOAspect 很好,但 LogControllerAspect 记录了两次。这 2 个 Java 文件是 here
    • 弄清楚了,这是一个 log4j 问题。不是 Spring AOP 问题。有关它的完整详细信息是here
    • “您还需要将 CGLIB 和 ASM 库作为 WAR/EAR 文件中的依赖项。” - 我没有添加这个就发布了
    【解决方案2】:

    我将说明一个替代解决方案(抱歉不是直接答案),但您想要做的最好通过拦截器和过滤器来完成。

    【讨论】:

    • 我无法使用方面来完成这项工作,所以我选择了拦截器路线。
    • 也就是说,如果有人可以提供,我仍然对解决方案感兴趣!
    • tommy,你从来没有说过为什么我上面的解决方案不起作用?我在当前在生产中运行的两个单独的应用程序中使用了它。拦截器和过滤器很好,但应用方面的语法更加丰富和灵活。
    猜你喜欢
    • 2017-03-21
    • 2015-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-15
    • 2011-02-07
    相关资源
    最近更新 更多