Spring ComponentScan 包结构

Spring ComponentScan package-structure

我的应用程序包含以下 classes:
Spring主要应用程序:

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

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

interface com.foo.bar.ClassToAutowire {
}

还有另一个 class 对字段使用所述接口:

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

@Autowired
ClassToAutowire autoClass;

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

}

但该字段不会自动装配:

Field autoClass in com.foo.appl.pack.ImplementationClass required a bean of type 'com.foo.bar.ClassToAutowire' that could not be found.

Action:

Consider defining a bean of type 'com.foo.bar.ClassToAutowire' in your configuration.

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

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

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

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

谢谢

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

中的路径

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

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

注释 class

@Component 表示一个注解的class是一个"component"。在使用基于注释的配置和 class 路径扫描时,此类 classes 被视为自动检测的候选对象。 reference @Component documentation

当使用Spring 时,默认启动它进行组件扫描。此组件扫描是在与 @SpringBootApplication 注释 class 所在的同一包中开始完成的。在您的情况下是 com.foo.appl 但这不包括 com.foo.bar.

最佳做法是将您的 @SpringBootApplication 注释 class 放在您能找到的最顶级包中,在您的情况下是 com.foo。这将扫描其下的所有包并将包括适当的组件。

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

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

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

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