Spring AOP 对Spring MVC的Controller切面拦截不起做用

1 问题描述

当使用Spring AOP对Controller层的Controller类的方法进行切面拦截,不起做用。AOP配置没有任何问题。web

2 排查过程

  1. Spring AOP配置没有任何问题;【正常】
  2. 断点调试:Spring源码断点调试,在调用Controller方法时,Controller的实例被JDK进行动态代理了;【不正常】
  3. Spring默认的代理方式为JDK动态代理;【正常】

3 解决问题

AOP有的人说拦截不到Controller。有的人说想拦AnnotationMethodHandlerAdapter截到Controller必须得拦截org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapterspring

首先AOP能够拦截到Controller的,这个是毋容置疑的其次须拦截AnnotationMethodHandlerAdapter也不是必须的。最起码我没有验证成功过这个。这个方式就不在这儿介绍说明了。express

AOP之因此有的人说拦截不到Controller, 缘由是该注解的Controller已被spring容器内部代理了。咱们只要把它交给cglib代理就能够了。Spring MVC的配置文件dispatcher-servlet.xml:bash

<!-- 通知spring使用cglib而不是jdk的来生成代理方法 AOP能够拦截到Controller -->
<aop:aspectj-autoproxy proxy-target-class="true" />
复制代码

4 问题总结

Spring MVC 和 Spring 整合的时候,SpringMVC的dispatcher-servlet.xml文件中配置扫描包,不要包含 service的注解,Spring的applicationContext.xml文件中配置扫描包时,不要包含controller的注解,以下所示:mvc

Spring MVC dispatcher-servlet.xml:app

<context:component-scan base-package="com.qding">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
复制代码

Spring MVC启动时的配置文件,包含组件扫描、url映射以及设置freemarker参数,让Spring不扫描带有@Service注解的类。为何要这样设置?由于springmvc.xml与applicationContext.xml不是同时加载,若是不进行这样的设置,那么,Spring就会将全部带@Service注解的类都扫描到容器中,等到加载applicationContext.xml的时候,会由于容器已经存在Service类,使得cglib将不对Service进行代理,直接致使的结果就是在applicationContext 中的事务配置不起做用,发生异常时,没法对数据进行回滚。以上就是缘由所在。url

一样的在Spring的applicationContext.xml配置以下:spa

<context:component-scan base-package="com.qding">           
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
复制代码

context:component-scan扫描指定的包中的类上的注解,经常使用的注解有:prototype

@Controller 声明Action组件
@Service    声明Service组件    @Service("myMovieLister") 
@Repository 声明Dao组件
@Component   泛指组件, 当很差归类时. 
@RequestMapping("/menu")  请求映射
@Resource  用于注入,( j2ee提供的 ) 默认按名称装配,@Resource(name="beanName") 
@Autowired 用于注入,(srping提供的) 默认按类型装配 
@Transactional( rollbackFor={Exception.class}) 事务管理
@ResponseBody
@Scope("prototype")   设定bean的做用域
复制代码
相关文章
相关标签/搜索