【问题标题】:Which packages are considered in the component scan by SpringSpring在组件扫描中考虑了哪些包
【发布时间】:2021-01-03 06:46:43
【问题描述】:

我有一个 spring boot 应用程序,它使用标记接口来定义应该用于组件扫描的包:

@ComponentScan(basePackageClasses = {ModelComponents.class, WebComponents.class, ServiceComponents.class})

ModelComponents 下的一个包中,定义了一个用作服务的接口,并在ServiceComponents 中实现了它,但不知何故没有被拾取。

在 spring 包上使用调试级别调试(VM 选项:-Dlogging.level.org.springframework=DEBUG)我可以看到前两个组件中的所有 spring bean 都被拾取,但第三个组件中没有。

How to turn on Spring's component-scan debugging info? 中描述的限制到更具体的包相比,启用此调试信息可提供更多输出,但我从中得到的只是日志输出,例如:

DEBUG | .c.a.ClassPathBeanDefinitionScanner |                        | Identified candidate component class: file [...\ActivityLogService.class]
DEBUG | .c.a.ClassPathBeanDefinitionScanner |                        | Identified candidate component class: file [...TopayMwApplicationProperties.class]
DEBUG | .c.a.ClassPathBeanDefinitionScanner |                        | Identified candidate component class: file [...ChallengeService.class]

这告诉了我所有关于找到的 bean 的信息,但它没有给出任何关于其他的提示:因为包被忽略而没有找到它们,或者 spring 查看了基本包并没有找到 bean?

有没有办法获取组件扫描考虑使用哪个包或使用哪个标记接口的信息?

如何在日志中识别?

【问题讨论】:

标签: java spring spring-boot


【解决方案1】:

在这里,Spring 将在您指定的那些类的包下查找组件。我的意思是Spring会搜索ModelComponents.class包、WebComponents.class包和ServiceComponents.class包下的组件。因此

  1. 如果您的实现类不在这些包之一下,那么它将被忽略。
  2. 如果你的实现类没有被注解为 Spring 组件,那么它将被忽略

【讨论】:

  • 我知道这一点,我的服务使用Service 进行注释,并且位于标记界面的同一个包(或子包)中。
  • 为什么不使用 basePackages 而不是 basePackageClasses?
  • 因为使用类型是重构安全的:如果你重命名包,你可能会忘记更新 basePackages 中的字符串,尽管有一些 IDE 支持。
  • 我明白了。为什么不让 Spring 通过不在 @ComponentScan 注释中定义任何包或类来自动定位它们。然后它会自动识别您的配置类和子包的同一包下的每个组件。
  • 并非所有 bean 都在应用程序类的子包中,我需要能够有选择性。
【解决方案2】:

显然无法通过日志检索此信息。 org.springframework.context.annotation.ComponentScanAnnotationParser 类确实将 basePackageClasses 数组从注解解析为 parse 方法中的包数组。

调试问题显示我使用了 3 个标记接口类,但只输出了 2 个包。

由于问题中的示例不是现实生活中的示例,因此它没有显示全部真相,这导致它:有两个同名的标记接口,但一个在另一个的子包中,一个来自子包被导入并在basePackageClasses中使用了两次。

因此,上面一个包中的 bean 不在被扫描的包中。

【讨论】:

    【解决方案3】:

    您提交的代码看起来是正确的,尽管正如其他评论者所提到的,这可能是您的课程安排问题。 我用来设置要扫描的包的代码是这样的:

    scanBasePackages = {"ru.company.package", "ru.company.anotherpackage"}
    

    尽管由于可能的拼写错误而不太安全,但它会明确设置包,并且可能会为您提供有关错误的更多信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-05
      • 2016-10-21
      • 2011-05-09
      • 1970-01-01
      • 1970-01-01
      • 2015-04-25
      • 1970-01-01
      • 2015-01-13
      相关资源
      最近更新 更多