今天搭建 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>
<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>
从代码可以看出,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. } }
之后,扫描时根据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; }
结论为:在使用 use-default-filters 属性时要分清楚需要扫描哪些包,是不是需要使用默认的 Filter 进行扫描。
简单总结就是 use-default-filters="false" 需要和 context:include-filter 一起使用,而不能和 context:exclude-filter 属性一起使用。
原文:https://www.cnblogs.com/KennyWang0314/p/12262197.html