记录下spring MVC 不能@Autowired

今天在项目新建一个功能模块,不能用@Autowired注入,看样子是@Service绑定错误,没有注入service等,提示Could not autowire. No beans of ‘xxxx’ type found

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientConfService': Injectionof autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private BookApp.ClientConf.dao.ClientConfMapper BookApp.ClientConf.service.ClientConfService.clientConfMapper;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type \[BookApp.ClientConf.dao.ClientConfMapper\]found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

首先检查spring mvc,因为用到了mybatis,一起检查组件扫描情况

在applicationContext-mybatis.xml中启用注解和扫描配置

<!-- 启用注解 -->
<context:annotation-config/>
<!-- 启用组件扫描,排除@Controller组件,该组件由springMvc配置扫描 -->
<context:component-scan base-package="SystemManage">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<context:component-scan base-package="BookApp">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<context:property-placeholder location="classpath:resource/dbConfig.properties"/>

配置正常,再检查spring-mvc.xml中注解扫描

<context:annotation-config/> 
<mvc:annotation-driven/>
<!-- 扫描Controller -->
<context:component-scan base-package="SystemManage">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
<!-- 扫描Controller -->
<context:component-scan base-package="BookApp">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>

也是正常

context:include-filter和context:exclude-filter区别:

spring的配置文件与springmvc的配置文件分开加载,在spring容器初始化的时候,会先加载(web.xml)<context-param>

中的配置,之后再加载<servlet>中的<init-param>。加载springmvc的时候,如果扫描到@service会重新加载这个service

的bean(都是没有aop配置事务控制的),可能会覆盖之前的service,导致service的事务失效。所以说我们一般分开加

载的时候在加载spring配置文件的时候只扫描@service和@Reposity这些类,就使用exclude,相当于黑名单;加载springmvc

的配置文件的时候,就使用include,相当于白名单

但是还是报错。。。。

后来发现需要配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中

在applicationContext-mybatis.xml中添加配置

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!--注入sqlSessionFactory -->
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    <!--给出需要扫描Dao接口包 -->
    <property name="basePackage" value="BookApp.*"/>
</bean>

看到了有人发的自动扫描源码,并给出解释

BeanDefinitionRegistryPostProcessor that searches recursively starting from a base package for
 * interfaces and registers them as {@code MapperFactoryBean}. Note that only interfaces with at
 * least one method will be registered; concrete classes will be ignored.
 * <p>

意思大概为:BeanDefinitionRegistryPostProcessor这个类会扫描你设置的BasePackage中的所有的接口(注意这里的所有),然后将他们注册到MapperFactoryBean中。然后还特意给出了提示:只有至少有一个方法的接口才会被注册,实现类会被忽略。

那么,跟我遇到的异常有什么关系呢?

我的项目中分为三层,dao层由Mybatis来负责管理,Service层也有接口和实现类,由Spring管理,上面也说了,这个类在扫描的时候会扫描所有的至少一个方法的接口,也就是只要符合条件的,都会被他扫描到并且任务是Mybatis的接口。

最后解决了!

完!