@ComponentScan具有多个配置类:基于注释的配置

时间:2017-02-08 10:51:25

标签: java spring spring-mvc component-scan

根据Spring Doc -

  

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

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

问题1 - 我们是否可以在@ComponentScan或所有 {{1}的任何中使用@Configuration 类?

问题2 -

我也在春天见过doc

@Configuration

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

编辑:基本上我对@Configuration @ComponentScan(basePackageClasses = { MyConfiguration.class }) public class MyConfiguration extends WebMvcConfigurerAdapter { ... } 的理解是扫描并注册立体声类型bean(例如@ComponentScan@componant@Controller等。),为什么我们是注册@Services Bean。

3 个答案:

答案 0 :(得分:7)

问题1 -

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

  1. @Configuration或中注册rootcontext bean dispatchersevletcontext
  2. 要在已注册的bean中导入此@Configuration 在容器中。
  3. 假设您正在使用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定义的包中存在的所有组件类。

答案 1 :(得分:1)

问题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指定为basepackageclasses的{​​{1}}属性的值?

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

因此,在您的回答中,所有这些类都将进行组件扫描,这些类存在于MyConfiguration.class所在的包中。
配置类以及标记类,以便组件扫描其他类。这也意味着所有带注释的类都将被注册,这些类存在于MyConfiguration.class所在的包中,包括MyConfiguration.class,因为它使用@Configuration注释进行注释
{{{ 1}}属性也可以包含其他类,如basepackageclasses

益处:
因此,如果重命名包,则没有问题,因为您有标记类,这有助于弹出查找包。这些标记类可能包含也可能没有任何内容,因为它只是作为查找包的标记。

答案 2 :(得分:0)

来自文档:

<强> Q1:

  

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

     

@Configuration类不仅可以使用组件扫描进行自举,还可以使用@ComponentScan 注释自行配置组件扫描:

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

<强> Q2:

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知道需要扫描哪些包,则可以在其他地方或方式进行扫描,您无需使用它。第二季度的代码只是春天能够做的一个例子。