Spring Aop对Controller层拦截失效问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Aop对Controller层拦截失效问题相关的知识,希望对你有一定的参考价值。

参考技术A 问题:当使用Spring AOP对Controller层的Controller类的方法进行切面拦截,不起作用。AOP配置没有任何问题。

分析:断点调试:Spring源码断点调试,在调用Controller方法时,Controller的实例被JDK进行动态代理了;

解决:Spring默认的代理方式为JDK动态代理,而Controller层是没有接口实现的,所以Jdk无法对Controller接口进行动态代理,接口就无法拦截。不用接口的代理方式我们自然想到cglib,于是增加了cglib的代理配置<aop:aspectj-autoproxy proxy-target-class="true" />

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

Spring MVC dispatcher-servlet.xml:

<context:component-scan base-package="com.service"><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 中的事务配置不起作用,发生异常时,无法对数据进行回滚。以上就是原因所在。

同样的在Spring的applicationContext.xml配置如下:

 <context:component-scan base-package="com.web"><context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /></context:component-scan>

扫描指定的包中的类上的注解,常用的注解有:

@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的作用域

Spring AOP拦截对Controller的请求时的配置失败

简单的说,就是父子容器的问题,将AOP的配置信息放在applicationContext.xml中,该配置文件被ContextLoaderListener加载,Spring会创建一个WebApplicationContext的上下文,称为父上下文(父容器),保存在 ServletContext中,key值为WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE。而spring-mvc.xml是DispatcherServlet 的配置文件,这样的servlet可以同时配置多个,每个 DispatcherServlet有一个自己的上下文对象(WebApplicationContext),称为子上下文(子容器),子上下文可以访问父上下文中的内容,但父上下文不能访问子上下文中的内容。 它也保存在 ServletContext中, key值是"org.springframework.web.servlet.FrameworkServlet.CONTEXT"+Servlet名称。当spring加载父容器的时候就会去找切入点,但是这个时候切入的controller是在子容器中的,父容器是无法访问子容器,所以就拦截不到。

 

所以把拦截扫描包得代码从 applicationcontent 中提取到 springmvc-servlet 的配置文件中 即可。

以上是关于Spring Aop对Controller层拦截失效问题的主要内容,如果未能解决你的问题,请参考以下文章

Spring AOP获取拦截方法的参数名称跟参数值

SpringMVC中配aop拦截不生效,咋回事

Spring aop 拦截不到Dao

spring boot aop日志管理(MongoDB)

SpringMVC中配aop拦截不生效,咋回事

AOP-代理拦截实现Redis缓存