多模块项目的 Spring Component Scan 问题

SpringBoot ComponentScan issue with multi-module project

我有一个带有 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);
    }   
}

现在令人惊讶的是,如果我 运行 这个应用程序使用 运行 As -> Spring Boot App 它工作正常。但是如果我 运行 它作为 运行 As -> Java Application 它失败并显示错误说它找不到在 myapp 中定义的 beans-核心模块。

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

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

如果 JPA 存储库或实体不在 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 我可以 运行 使用 运行 As -> Java 应用程序.

但仍然不确定当 运行 As -> Spring Boot App!!

时它是如何正常工作的

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

战斗

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

我在 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;
    }
}