【Spring】context:component-scan包扫描问题

Spring 项目bean 无法注入或者初始化,可能是扫描问题,下面分两种情况研究
1.配置的bean 没有被扫描
先说一下<context:component-scan base-package=“com.summer”> ,这个标签有一个use-default-filters属性,该属性默认为true(表示扫描到有@Component @Controller@Service @Reposity等这些注解的类,则把这些类注册为bean。所以如果仅仅是在配置文件中这么写<context:component-scan base-package=“com.summer”> Use-default-filter此时为true那么会对base-package包或者子包下的所有的进行java类进行扫描,并把匹配的java类注册成bean。

context:component-scan 标签有两个子标签: context:include-filter 和 context:exclude-filter

context:include-filter 仅仅扫描指定得范围-----下面配置表明仅仅扫描com.summer包下@Controller注解得bean,使用include标签需要注意必须添加use-default-filters=“false” ,否则context:include-filter 此过滤器无效,因为该属性默认为true,

<context:component-scan base-package="com.summer" use-default-filters="false">
		<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>	
</context:component-scan>

context:exclude-filter 仅仅扫描除了exclude外的范围—下面配置表明扫描com.summer包下除了@Controller注解以外的bean。

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

通常项目中使用的是类似上面的配置,这样可以防止重复扫描,避免覆盖,引起事务失效问题,因为springMVC 和spring 这两个容器是父子容器关系,mvc 是子容器,spring 是父容器,子容器可以看见父容器中的注册的Bean,反之就不行。

经测试有如下发现:
use-dafault-filters=”true”的情况下:context:exclude-filter生效,context:include-filter无效
use-dafault-filters=”false”的情况下:context:exclude-filter生效,context:include-filter生效

use-dafault-filters=”false”的情况下:可以指定不需要扫描的路径来排除扫描这些文件,可以指定需要扫描的路径来进行扫描。可以说use-default-filters="false"属性是专门和context:include-filter子标签一起使用,这样可以更加自由地指定哪些注解由扫描器扫描.

因此如果bean没有被注入时候检查扫描是否正确,确保都被扫描了

2.配置的bean确定被扫描但是还是无法注入

如果确定所有的bean都在扫描范围内还是无法注入,可能是因为设置了懒加载(default-lazy-init=“true”)而又没有在其他地方引入。常见于某一个单独的service(例如单独的开启一个service 专门处理一些事情,比如监听),此service 如果没有在其他地方调用,但由于是懒加载,因此不会实例化。最明显的特征是,直接在Controller 层 @Autowired引用的时候就会被加载,不引用就不被加载。

对于懒加载 —啰嗦一句

懒加载:对象使用的时候才去创建,节省资源,但是不利于提前发现错误。

非懒加载:容器启动的时候立刻创建对象。消耗资源。利于提前发现错误。

当scope=“prototype” (多例)时,默认以懒加载的方式产生对象。

当scope=“singleton” (单例)时,默认以非懒加载的方式产生对象。

参考配置

spring-core.xml:
基包值为整个项目,use-default-filters为默认true,然后指定不扫描@Controller

<!-- 自动扫描 Service层 -->
<context:component-scan base-package="com.lich.springProject">
	<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

spring-mvc.xml:
基包值为整个项目,use-default-filters设置为false,然后指定只扫描@Controller

!-- 自动扫描该包,使SpringMVC认为包下用了@controller注解的类是控制器 -->
<context:component-scan base-package="com.lich.springProject" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

重复扫描导致事务失败的解决方案及深入分析

参考链接

总结:

  1. 规范操作:spring-core.xml应该扫描所有非@Controller的所有bean,spring-mvc.xml应该只扫描@Controller的bean。
  2. 规范操作:spring-core.xml中设置开启事务支持,所有事务都在@Service的类中控制。
  3. Spring容器的bean需要注入其它bean时,只能从自己容器中找,访问不到MVC容器的bean;MVC容器的bean需要注入其它bean时,先从自己容器中找,若找不到才会去Spring容器中找。
  4. 若Spring容器和MVC容器都扫描了同一个@Component类,则各创建一个bean实例,但beanName相同。若确定程序中所有非@Controller的bean都没有依赖@Controller的bean(正常情况就是这样),可以在Spring容器扫描所有bean,包括@Controller的,因为这样@Controller的bean就不会被使用到(即使是访问项目时也是使用的MVC容器的controller-bean),只是多余创建了而已。
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值