多模块项目的 Spring Boot 组件扫描问题

Posted

技术标签:

【中文标题】多模块项目的 Spring Boot 组件扫描问题【英文标题】:SpringBoot ComponentScan issue with multi-module project 【发布时间】:2018-08-23 03:22:30 【问题描述】:

我有一个带有 myapp-core 和 myapp-web 模块的 myapp 父 pom 类型的 maven 项目。 myapp-core 模块作为依赖项添加到 myapp-web。

myapp-core 模块中的所有类都位于根包 com.myapp.core 中,myapp-web 模块中的所有类都位于根包 com.myapp.web 中>

主要的 Application.java 也在 com.myapp.web 包中。由于我的核心模块根包不同,我将 ComponentScan 的通用基础包 "com.myapp" 包括在内,如下所示:

@Configuration
@ComponentScan(basePackages="com.myapp")
@EnableAutoConfiguration
public class Application 
    public static void main(String[] args) 
        SpringApplication.run(Application.class, args);
       

现在令人惊讶的是,如果我使用 Run As -> Spring Boot App 运行这个应用程序,它运行良好。但是,如果我将它作为 Run As -> Java Application 运行,它会失败并显示错误说它找不到在 myapp-core 模块中定义的 bean。

如果我将我的 Application.java 移动到 com.myapp 包,它工作正常。 即使我也将它作为 Java 应用程序运行,它也应该可以工作,对吧?

【问题讨论】:

仅当类路径正确时,当您将其作为 Java 应用程序运行时。因此,请检查您的运行配置,如果包含所有依赖项。 我在这两种情况下都有相同的 pom 依赖项,并且我正在运行相同的 Application.java。 我不是在谈论 POM,我是在谈论类路径,IDE 正在为您的运行配置构建它。由于您没有指定 IDE,我无法为您提供更多帮助。 我可以说这不是因为类路径。因为如果我只是将 Application.java 移动到 com.myapp 包,它就可以正常工作。所以我想它必须与@ComponentScan 做点什么。 【参考方案1】:

在为 spring 启用调试日志级别并查看大量日志后,我发现扫描各种组件(如 JPA 存储库、JPA 实体等)取决于 Application.java 的包名称。

如果 JPA Repositories 或 Entities 不在 Application.java 的包的子包中,那么我们需要如下明确指定它们:

@Configuration
@ComponentScan(basePackages="com.sivalabs.jcart")
@EnableAutoConfiguration
@EnableJpaRepositories(basePackages="com.sivalabs.jcart")
@EntityScan(basePackages="com.sivalabs.jcart")
public class Application

    public static void main(String[] args) 
        SpringApplication.run(Application.class, args);
    

有了以上额外的@EnableJpaRepositories@EntityScan,我可以使用Run As -> Java Application来运行它。

但仍然不确定 Run As -> Spring Boot App 时它是如何正常工作的!!

无论如何我认为将我的Application.java 移动到com.myapp 包而不是与SpringBoot 斗争!

【讨论】:

spring boot 文档建议把主类放在根目录下,所以把它移到com.myapp。如果路径正确,您无需担心,因为来自根目录的所有内容都会被扫描。【参考方案2】:

我也有同样的问题。只有添加@EnableJpaRepositories 注解才能解决问题。我试图在@SpringBootApplication 中定义basePackages,但无济于事。 我认为Application类的包被馈送到JpaRepositories的扫描过程中,但是@SpringBootApplication中定义的其他包被忽略了。 它看起来像是 Spring Boot 的错误/改进。

【讨论】:

【参考方案3】:

我在 Redis 存储库中遇到了类似的问题,该问题以类似的方式修复:


@Configuration
@EnableConfigurationProperties(RedisProperties.class)
@RequiredArgsConstructor
@EnableRedisRepositories(basePackages = "com.example.another")
public class RedisConfig 

    private final RedisConnectionFactory redisConnectionFactory;

    @Bean
    public RedisTemplate<?, ?> redisTemplate() 
        RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
        template.setConnectionFactory(redisConnectionFactory);
        template.afterPropertiesSet();
        return template;
    


【讨论】:

以上是关于多模块项目的 Spring Boot 组件扫描问题的主要内容,如果未能解决你的问题,请参考以下文章

配置 Spring Boot 多模块项目的问题

自主开发的、带有 @Component 的组件在Spring Boot 项目中不生效的解决方法

Spring-Boot 多模块项目加载属性文件

多模块 Spring Boot 项目中的 Gradle 依赖插件

多模块 Gradle 项目 - 从 Spring-Boot 1.5 迁移到 2.1

Spring Boot 之 spring.factories