【问题标题】:@ComponentScan with multiple configuration class : Annotation Based Configuration@ComponentScan 具有多个配置类:基于注释的配置
【发布时间】:2017-06-25 22:49:47
【问题描述】:

根据 Spring Doc-

配置组件扫描指令以与@Configuration 类一起使用。提供与 Spring XML 的 <context:component-scan> 元素并行的支持。

在我的 Spring Web 应用程序中有多个标记为 @Configuration 的文件,以便在 Spring 容器中注册 @component bean-

问题1-我们可以在@Configuration 类的任何一个或所有@Configuration 类中使用@ComponentScan吗? p>

问题2-

我在春天也见过doc

@Configuration
@ComponentScan(basePackageClasses = { MyConfiguration.class })
public class MyConfiguration extends WebMvcConfigurerAdapter {
...
}

为什么在这里扫描配置类本身。

edit:基本上我对@ComponentScan的理解是扫描和注册立体类型bean(例如-@componant@Controller@Services等),为什么我们要注册@Configuration Bean。

【问题讨论】:

  • 为什么要扫描配置类本身?”:因为我们不是; basePackageClasses - 名字里有线索。
  • 不清楚,你能解释更多吗,很少有疑问:1-为什么我们扫描配置类它意味着@Component,2-如果需要如何知道我们是否是basePackageClasses,3 -为什么在现实世界应用程序中的任何@Configuration 类中都不需要这样做。

标签: java spring spring-mvc component-scan


【解决方案1】:

对于您的问题 1 -

是的,你可以使用@ComponentScan任何配置bean在spring容器中注册注册一个bean。你可以通过任何方式将一个bean注册到容器中以下方式-

  1. 使用@Configurationrootcontext注册bean或 dispatchersevletcontext
  2. 在任何@Configuration bean(已在容器中注册)中导入一个类。

假设-您有 MvcConfig 正在扫描组件的类-

@ComponentScan(basePackages = {"xxxx","yyyy","zzzz"})
@Configuration
public class MvcConfig  {
....
}

要在容器中注册MvcConfig,您必须这样做-

要么

new AnnotationConfigWebApplicationContext().register(MvcConfig.class);

或者

new AnnotationConfigWebApplicationContext().register(AnotherConfig.class);

@Configuration
@Import({MvcConfig.class})
public class AnotherConfig  {
....
}

关于您的问题 2 -

这里 spring 不仅注册了MyConfiguration.class,还注册了 MyConfiguration 定义的包中存在的所有组件类。

【讨论】:

    【解决方案2】:

    问题 1 的解答:
    是的,您可以在尽可能多的配置类中使用@Componentscan。这完全取决于你。它只是将某些特定包的各种注释类注册为 bean。因此,如果您仅使用一个@Componentscan 扫描了所有带注释的类组件,就足够了,因为您想要的所有必需的bean都已在DispatcherServlet 容器。

    问题 2 的解答:

    @Configuration
    @ComponentScan(basePackageClasses = { MyConfiguration.class })
    public class MyConfiguration extends WebMvcConfigurerAdapter {
    ...
    }
    

    您的问题:为什么要扫描配置类本身?
    这个@ComponentScan(basePackageClasses = { MyConfiguration.class }) 以 MyConfiguration.class 为例。问题是这意味着什么?

    通过basepackage 属性或basepackageclasses 组件扫描包有两种方法。这两个是相同的,但使用basepackageclasses 有两个好处:
    它既是类型安全的,又为未来的重构添加了 IDE 支持
    这仅仅意味着,将来,您可能会重命名(通过重构)一些基本备份,并且由于您已经重命名了基本包,如果您使用了 basepackageclasses 属性,则不需要在配置类中更改 @ComponentScan。

    现在回到你的第二个问题。为什么 MyConfiguration.class 被指定为 @Componentscanbasepackageclasses 属性的值?

    首先,让我们知道这一点:
    basepackageclasses 属性采用代表某个标记类的字符串值。该标记类告诉:嘿!注册该类所在包中存在的所有类,包括该类

    因此,在您的回答中,所有这些类都将被组件扫描,它们存在于 MyConfiguration.class 所在的包中。

    因此,Myconfiguration.class 充当 Configuration 类以及 marker 类来组件扫描其他类。这也意味着所有带注释的类都将被注册,它们存在于 MyConfiguration.class 所在的包中,包括 MyConfiguration.class,因为它使用 @Configuration 注释进行注释

    basepackageclasses 属性也可以有其他类,比如com.abc.org.Marker.class

    好处:
    所以,如果你重命名包,没有问题,因为你有标记类,可以帮助 spring 找到包。这些标记类内部可能有也可能没有任何内容,因为它只是充当查找包的标记。

    【讨论】:

      【解决方案3】:

      来自文档:

      第一季度:

      @Configuration 使用 @Component 进行元注释,因此 @Configuration 类是组件扫描的候选对象(通常使用 Spring XML 的元素),因此也可以像任何常规 @Component 一样利用 @Autowired/@Inject。

      @Configuration 类不仅可以使用组件扫描进行引导,还可以自己使用@ComponentScan注解配置组件扫描:

      @Configuration
      @ComponentScan("com.acme.app.services")
      public class AppConfig {
       // various @Bean definitions ...
      }
      

      第二季度:

      basePackageClasses

      public abstract Class<?>[] basePackageClasses
      

      basePackages() 的类型安全替代方案,用于指定要扫描带注释组件的包。 将扫描指定的每个类的包


      回答您编辑的问题

      在某些时候,您需要告诉 Spring 您的应用程序需要的 bean 在哪里。您可以使用例如:

      public static void main(String[] args) {  
          AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
          ctx.scan("com.acme");  
          ctx.refresh();
          MyService myService = ctx.getBean(MyService.class);
      }
      

      或使用旧的 xml 样式:

      <context:component-scan base-package="com.acme" />
      

      在@Configuration 级别使用@ComponentScan,您可以确保该配置类的所有依赖项都可用。将 @CompenentScan 与 basePackageClasses 一起使用,您将在指定的类所在的同一包下注册所有可用组件。

      如果你已经让 spring 知道它需要扫描哪些包,在不同的地方或方式,你不需要使用它。 Q2 中的这段代码只是 Spring 能够做什么的一个示例。

      【讨论】:

      • 答案就是您的问题的答案。正如文档所述,Q1 的答案是肯定的。 Q2 的答案是您不是在扫描配置类,而是在扫描指定类目录下的类路径,正如文档中所说的那样。但是您似乎没有正确询问,因为现在您正在询问不同的内容并且您已经编辑了原始问题。如果您没有正确解释自己,请不要对答案投反对票(当然,如果是您)。我已经编辑了我的答案。
      猜你喜欢
      • 2010-09-15
      • 2017-05-27
      • 1970-01-01
      • 2015-12-06
      • 1970-01-01
      • 2016-08-02
      • 2012-01-15
      • 2015-07-11
      • 1970-01-01
      相关资源
      最近更新 更多