【问题标题】:Spring ComponentScan package-structureSpring ComponentScan 包结构
【发布时间】:2017-08-22 07:33:13
【问题描述】:

我的应用程序包含以下类:
SpringMainApplication:

@SpringBootApplication
@ComponentScan(basePackages = {"com.foo"})
class com.foo.appl.SpringMainApplication {
... some code...
}

应该用于自动装配字段的接口:

interface com.foo.bar.ClassToAutowire {
}

还有另一个使用该接口作为字段的类:

@Component
class com.foo.appl.pack.ImplementationClass {

@Autowired
ClassToAutowire autoClass;

@Scheduled(fixedRate = 60000)
public void startStuff() {
  // do something...
  }

}

但该字段不会自动装配:

com.foo.appl.pack.ImplementationClass 中的字段 autoClass 需要一个 找不到类型为“com.foo.bar.ClassToAutowire”的 bean。

行动:

考虑在你的 配置。

我猜 Spring 不喜欢我的包结构?

com.foo.bar.ClassToAutowire
com.foo.appl.SpringMainApplication
com.foo.appl.pack.ImplementationClass

@SpringBootApplication 是否必须在根包中并且所有组件都必须在子包中?如果是这样,我该如何解决我的“问题”,因为 ClassToAutowire 来自导入的 JAR。

basePackge 更改为com.foo.bar 时,应用程序启动,但计划的方法不会运行。

谢谢

【问题讨论】:

  • 将您的SpringMainApplication 放入com.foo 或将@ComponentScan("com.foo") 添加到您的SpringMainApplication
  • 虽然将SpringMainApplication 放入com.foo 可以解决我的问题,但我想保持我的包结构不变...@ComponentScan("com.foo") 已添加到 SpringMainApplication。
  • 这是您在顶级包中的起点的最佳实践。如我的评论中所述,如果您真的不希望这样做(这有几个缺点,尤其是在开始使用更多框架时)添加@ComponentScan("com.foo"),但例如这不会自动检测 Spring Data 存储库、JPA 实体等。您将需要一个很多额外的配置,否则你可以免费获得。

标签: java spring spring-boot component-scan


【解决方案1】:

使用 Spring Boot 时,默认情况下会进行组件扫描。此组件扫描是在与 @SpringBootApplication 注释类所在的相同包中完成的。在您的情况下是 com.foo.appl 但是这不包括 com.foo.bar

最好的做法是将您的 @SpringBootApplication 注释类放在您能找到的最顶层包中,在您的情况下是 com.foo。这将扫描它下面的所有包并包含适当的组件。

您还可以将@ComponentScan("com.foo") 添加到您的@SpringBootApplication 注释类中,让它开始扫描不同的包或(@SpringBootApplication(basePackage="com.foo")

如果依赖 jar 中不再有组件,您还可以添加 @Bean 方法来创建所需类的实例。

@Bean
public ClassToAutowire classToAutowire() {
    return new ClassToAutowire();
}

第二种方法的缺点是,当使用 Spring Data 或 JPA 之类的东西时,您还必须手动配置它们(添加诸如 @EnableJpaRepositories@EntityScan 之类的东西)。当使用/添加不同的框架时,这会增长,当您将类放在顶级包中时,情况并非如此,因为所有包都被考虑在内。

【讨论】:

    【解决方案2】:

    您应该实现接口 com.foo.bar.ClassToAutowire 并使用 @Component

    注释类

    @Component 表示带注释的类是“组件”。在使用基于注释的配置和类路径扫描时,此类类被视为自动检测的候选对象。 reference @Component documentation

    【讨论】:

      【解决方案3】:

      @SpringBootApplication 是否必须在根包中,所有组件都必须在子包中? 不,@SpringBootApplication 可以放在任何地方,但您需要在@ComponentScan 中提供正确的路径

      如果 ClassToAutowire 类的实现来自外部包,则需要从该 jar 导入 spring 配置。这意味着定义使用@Configuration 注解的配置类,然后使用@Import 注解将此配置导入您的ImplementationClass。 此处描述的另一个使用 spring 自动配置的 woulb:https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html

      【讨论】:

        猜你喜欢
        • 2018-12-28
        • 2015-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-25
        • 2015-03-28
        • 2019-04-09
        • 2018-06-14
        相关资源
        最近更新 更多