use-default-filters 属性的说明

今天搭建 SSM 开发框架,整体完成后,启动 tomcat 报错,报错信息为

org.springframework.beans.factory.BeanCreationException: Error 
creating bean with name 'employeeController': Injection of 
autowired dependencies failed; nested exception is 
org.springframework.beans.factory.BeanCreationException: Could 
not autowire field: private 
com.kenny.mybatis.service.EmployeeService 
com.kenny.mybatis.controller.EmployeeController.employeeService; 
nested exception is 
org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type 
[com.keyyn.mybatis.service.EmployeeService] 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)}

Caused by: 
org.springframework.beans.factory.BeanCreationException: Could 
not autowire field: private 
com.kenny.mybatis.service.EmployeeService 
com.kenny.mybatis.controller.EmployeeController.employeeService;
 nested exception is 
org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type 
[com.kenny.mybatis.service.EmployeeService] 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=tr

查看错误信息表示没有扫描到 Service,首先定位到 context:component-scan 标签 分别在 spring-servelt.xml (管理Controller)& applicationContext.xml(管理其他 bean ) 都配置了该属性 

<context:component-scan base-package="com.kenny.mybatis" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
spring-servlet.xml 片段
 <context:component-scan base-package="com.kenny.mybatis" use-default-filters="false">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
applicationContext.xml

从代码可以看出,use-default-filters 该属性都设置为了 false ,默认为 true;Spring 会根据 该属性是否为 true 执行以下代码

protected void registerDefaultFilters() {
  this.includeFilters.add(new AnnotationTypeFilter(Component.class));
  ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
  try {
    this.includeFilters.add(new AnnotationTypeFilter(
      ((Class<? extends Annotation>) cl.loadClass("javax.annotation.ManagedBean")), false));
    logger.info("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
  }
  catch (ClassNotFoundException ex) {
    // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
  }
  try {
    this.includeFilters.add(new AnnotationTypeFilter(
      ((Class<? extends Annotation>) cl.loadClass("javax.inject.Named")), false));
    logger.info("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
  }
  catch (ClassNotFoundException ex) {
    // JSR-330 API not available - simply skip.
  }
}
use-default-filters=true 执行代码

之后,扫描时根据include-filter/exclude-filter来判断你的Bean类是否是合法的

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
 for (TypeFilter tf : this.excludeFilters) {
   if (tf.match(metadataReader, this.metadataReaderFactory)) {
      return false;
   }
 }
 for (TypeFilter tf : this.includeFilters) {
   if (tf.match(metadataReader, this.metadataReaderFactory)) {
      AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
      if (!metadata.isAnnotated(Profile.class.getName())) {
         return true;
      }
      AnnotationAttributes profile = MetadataUtils.attributesFor(metadata, Profile.class);
      return this.environment.acceptsProfiles(profile.getStringArray("value"));
    }
  }
 return false;
}
include/exclude

结论为:在使用 use-default-filters 属性时要分清楚需要扫描哪些包,是不是需要使用默认的 Filter 进行扫描。

简单总结就是 use-default-filters="false" 需要和 context:include-filter 一起使用,而不能和 context:exclude-filter 属性一起使用。

 

posted @ 2020-02-04 23:56  KennyWang0314  阅读(328)  评论(0编辑  收藏  举报