zoukankan      html  css  js  c++  java
  • Spring AOP无法拦截Controller中的方法

    想使用AOP Annotation配置Spring MVC的Controller进行拦截, 发现无法拦截Controller的方法, 却可以拦截Service层的方法.

    一开始:

    Spring的配置文件application.xml包含了 开启AOP自动代理,Service扫描配置,以及Aspect的自动扫描配置

    代码1:application.xml
    
    <aop:aspectj-autoproxy/>
    
    <context:component-scan base-package="com.example.sdk.service">
    <context:component-scan base-package="com.hodc.sdk.aspect"/>

    Spring MVC的配置文件spring-mvc.xml主要内容是Controller层的自动扫描配置.

    代码2:spring-mvc.xml
    
    <context:component-scan base-package="com.hodc.sdk.controller" />

    增强代码为如下:

    复制代码
    代码3
    
    全限定名:com.example.sdk.aspect.ControllerAspect
    
    @Component
    @Aspect
    public class ControllerAspect {
           @Around(value = "execution(* com.hodc.sdk.controller.json.hadoop.HadoopClusterManage.*JsonWithException(..))") //1
    
    //   @Around(value = "within(@org.springframework.stereotype.Controller *)") //2
    
    //    @Around(value = "execution(* org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(..))") //3
       public Object test(ProceedingJoinPoint joint) {
    
    
           Result result = new Result();
    
           System.out.println("in aspect");
           result = (Result) joint.proceed();
           return result;
    
    
    }
    复制代码

     

    需要被拦截的方法如下:

    复制代码
    代码4
    
    全限定名:  com.example.sdk.controller.HadoopClusterManage#listVirtualHiveDBSJsonWithException
    
    @RequestMapping(value = "listVirtualHiveDBS.do", produces = "application/json")
       public
       @ResponseBody
       Result listVirtualHiveDBSJsonWithException(@RequestParam("clusterId") int clusterId) {
           Result result = new Result();
           List<Db> dbs = syncServiceForWeb.listVirtualHiveDBS(clusterId);
           result.setData(dbs);
           return result;
       }
    复制代码

    发现这样配置并没有用, 这个方法无法被拦截, 参照网上搜索的结果, 将@Around的PointCut改成代码3中2,3写法也没有作用.

    参照http://stackoverflow.com/questions/17834958/spring-aop-is-not-working-in-with-mvc-structure?rq=1

    因为Spring的Bean扫描和Spring-MVC的Bean扫描是分开的, 两者的Bean位于两个不同的Application, 而且Spring-MVC的Bean扫描要早于Spring的Bean扫描, 所以当Controller Bean生成完成后, 再执行Spring的Bean扫描,Spring会发现要被AOP代理的Controller Bean已经在容器中存在, 配置AOP就无效了.

    同样这样的情况也存在于数据库事务中, 如果Service的Bean扫描配置在spring-mvc.xml中, 而数据库事务管理器配置在application.xml中, 会导致数据库事务失效, 原理一样.

    所以这里 ,我们需要把AOP放置在Controller扫描配置的文件中.

    Spring的配置文件application.xml包含了 开启AOP自动代理,Service扫描配置, 现在只包含了service的自动扫描配置

    1. 代码5:application.xml
      
      <context:component-scan base-package="com.example.sdk.service">

    Spring MVC的配置文件spring-mvc.xml主要内容是Controller层的自动扫描配置,添加了开启AOP自动代理,以及Aspect的自动扫描配置

    代码6:spring-mvc.xml
    <aop:aspectj-autoproxy/>
    <context:component-scan base-package="com.hodc.sdk.aspect"/>
    <context:component-scan base-package="com.hodc.sdk.controller" />


    这样配置情况下代码3的3种pointcut都是有效的,但是第一种是最精确的.

  • 相关阅读:
    GCD与LCM
    命名空间的使用
    [模板][持续更新]欧拉回路与欧拉路径浅析
    二进制GCD算法解析
    [模板]LCA的倍增求法解析
    [模板]字符串哈希的简易做法
    11、Android--屏幕适配
    10、Android--Shape
    09、Android--Fragment
    08、Android--BroadcastReceiver
  • 原文地址:https://www.cnblogs.com/PengChengLi/p/10190891.html
Copyright © 2011-2022 走看看