在Eclipse STS中本地运行含子项目的Spring Boot应用遇Bean扫描问题
先梳理下你的项目结构:
root project |-- controller |-- core |-- widgets |-- widgetA |-- widgetB
以及你遇到的核心问题:部署到Tomcat时通过context.xml配置JarResources能正常扫描所有Bean,但STS本地以Spring Boot App启动controller时,无法找到WidgetInterface的实现类,报错如下:
May 22, 2018 2:32:00 PM org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext refresh
WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'Controller': Unsatisfied dependency expressed through field 'widgetMap'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.util.Map<java.lang.String, com.mycompany.project.widgets.WidgetInterface>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
System is shutting down
May 22, 2018 2:32:00 PM org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor shutdown
INFO: Shutting down ExecutorService 'getAsyncExecutor'
May 22, 2018 2:32:00 PM org.apache.catalina.core.StandardService stopInternal
INFO: Stopping service [Tomcat]
May 22, 2018 2:32:00 PM org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener logAutoConfigurationReport
INFO: Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
May 22, 2018 2:32:00 PM org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter report
SEVERE: ***************************
APPLICATION FAILED TO STARTDescription:
Field widgetMap in com.mycompany.project.controller.Controller required a bean of type 'com.mycompany.project.widgets.WidgetInterface' that could not be found.
Action:
Consider defining a bean of type 'com.mycompany.project.widgets.WidgetInterface' in your configuration.
问题根源
本地STS运行Spring Boot时,默认只会扫描controller项目本身的包路径,而widgets作为独立项目,即使打包成jar,若未正确配置依赖和扫描范围,Spring无法自动识别其中的Bean。而部署时通过context.xml手动指定了JarResources的加载路径,相当于扩展了类加载范围,所以能正常扫描。
针对性解决方案
1. 确保controller项目正确依赖widgets项目
如果是Maven项目,在controller的pom.xml中添加widgets的依赖:
<dependency> <groupId>com.mycompany.project</groupId> <artifactId>widgets</artifactId> <version>你的版本号</version> <scope>compile</scope> </dependency>
- 先在widgets项目执行
mvn clean install,将其安装到本地Maven仓库; - 在STS中右键controller项目 -> Maven -> Update Project,确保依赖被正确引入。
如果是Gradle项目,在build.gradle中添加:
implementation 'com.mycompany.project:widgets:你的版本号'
2. 扩展Spring Boot的组件扫描范围
在controller项目的主启动类上,通过@ComponentScan指定包含widgets项目的包路径,确保Spring能扫描到其中的Bean:
@SpringBootApplication @ComponentScan(basePackages = { "com.mycompany.project.controller", "com.mycompany.project.widgets" // 添加widgets的根包 }) public class ControllerApplication { public static void main(String[] args) { SpringApplication.run(ControllerApplication.class, args); } }
注意:如果widgets中的Bean是通过
@Configuration类的@Bean方法定义的,也要确保该配置类所在的包被包含在扫描范围内。
3. 配置STS本地运行的部署组件
STS本地运行时,需要确保widgets项目的类被加载到controller的运行环境中:
- 右键controller项目 -> Properties -> Deployment Assembly;
- 点击Add -> Project -> 选择widgets项目 -> 确认添加;
- 应用配置后重新启动Spring Boot App。
4. 解决Tomcat Redeploy失效的类加载问题
针对你提到的Tomcat redeploy功能失效,确实是类加载器锁文件导致的,可以在context.xml中添加如下属性优化:
<Context antiResourceLocking="true" antiJARLocking="true"> <!-- 你的JarResources配置内容 --> </Context>
这两个属性会减少Tomcat对资源文件和jar包的锁定,提升redeploy的成功率。
内容的提问来源于stack exchange,提问作者zeusalmighty

