Spring和springmvc父子容器注解扫描问题详解

一、Spring容器和springmvc容器的关系如下图所示:

在这里插入图片描述

Spring和springmvc和作为两个独立的容器,会把扫描到的注解对象分别放到两个不同的容器中,

Springmvc容器是spring容器的一部分,他们访问对象的范围如下所示:

①:springmvc子容器可以访问spring父容器中的对象

②:spring父容器不能访问springmvc子容器中的对象

在实际应用中的实例

一般情况下,一个spring / springmvc / mybatis 组合的框架中,会存在以下几个配置文件:

applicationContext-service.xml 文件

<!-- 配置service层的组件扫描器 -->

<context:component-scan base-package="com.prozhu.service"></context:component-scan>

说明:在这个里面存在着一个spring的注解扫描器。用来扫描@Service的注解

Springmvc.xml 文件

<context:component-scan base-package="com.prozhu.controller" />

说明:这个里面存在着springmvc的注解扫描器,专门用来扫描@Controller的注解

然后呢?有点同学可能会想,我能不能合并成一个注解扫描器,来完成对象注入的问题?将配置文件中的注解扫描器更改为如下配置:

在applicationContext-service.xml文件中进行全局扫描的配置,而在springmvc中不配置注解扫描器

<context:component-scan base-package="com.prozhu" />

说明:用这个扫描器分别扫描service层和controller层的注解:@Service /@Controller / @Autowired
当一旦采用这种方式之后,spring会将扫描的对象都会存放到spring的容器,而不会放到springmvc子容器中,当访问项目的时候,springmvc找不到处理器映射器,和其对应的Controller,进而报404错误!springmvc是处理映射请求,而spring是bean容器。spring扫描后将@Controller注解视为一个对象保存在容器中,如果不在mvc中启动扫描@Controller注解的话那么即使访问该映射的路径(@RequestMapping路径)下的文件也会报错404,因为springmvc找不到,因此必须要让springmvc框架去扫描@Controller才能真正的映射到指定路径。

不用spring容器,只用springmvc容器行不行呢?

答案:是可以的,在这个里面可以同时扫描Controller层、service层、dao层的注解。

在springmvc 和 spring 都有注解扫描的前提下,能不能将事务配置在Controller层?

答案:是不能的,因为事务管理器是配置在spring容器中的,如果将事务配置在Controller层的话,spring容器就访问不了springmvc子容器,

进而无法访问到事务对象。进而导致事务失效。

总结:springmvc 扫描路径设置到Controller注解所在包路径。spring扫描非Controller注解所在的包路径。这样也是官方推荐的扫描方式。
例如在spring扫包设置如下,使用context:exclude-filter标签排除controller注解

<context:component-scan base-package="exampleBean">
    <context:exclude-filter type="annotation"
        expression="org.springframework.stereotype.Controller" />
</context:component-scan>
发布了25 篇原创文章 · 获赞 4 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/liuhaiquan123521/article/details/94061017