8

根据 Spring Doc-

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

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

Question1-我们可以@ComponentScan 在任何@Configuration班级 或所有 @Configuration班级中使用吗?

问题2-

我也在春季文档中看到

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

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

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

4

3 回答 3

8

对于您的问题 1 -

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

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

假设-您有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

于 2017-02-15T08:58:06.740 回答
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. 这两个是相同的,但 usingbasepackageclasses有两个好处:
它既是类型安全的,又为未来的重构添加了 IDE 支持
这仅仅意味着,在未来,您可以重命名(通过重构)一些基础 backage,因为您已经重命名基本包,如果您使用了basepackageclasses属性,则无需更改配置类中的 @ComponentScan 。

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

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

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

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

basepackageclasses属性进行了注释,也可以具有其他类,例如com.abc.org.Marker.class

Benefit:
所以,如果你重命名包,没有问题,因为你有标记类,这有助于春天找到包。这些标记类内部可能有也可能没有任何内容,因为它只是作为查找包的标记。

于 2017-02-15T09:46:00.587 回答
0

From the documentation:

Q1:

@Configuration is meta-annotated with @Component, therefore @Configuration classes are candidates for component scanning (typically using Spring XML's element) and therefore may also take advantage of @Autowired/@Inject like any regular @Component.

@Configuration classes may not only be bootstrapped using component scanning, but may also themselves configure component scanning using the @ComponentScan annotation:

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

Q2:

basePackageClasses

public abstract Class<?>[] basePackageClasses

Type-safe alternative to basePackages() for specifying the packages to scan for annotated components. The package of each class specified will be scanned.


Answer for your edited question

At some point you need to say to Spring where the beans your app needs are. You can use for example:

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

or using old xml style:

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

Using @ComponentScan at @Configuration level you are making sure all the dependencies for that config class are going to be available. Using @CompenentScan with basePackageClasses you are registering all the components available under the same package the class specified is.

If you have already let spring know what packages it needs to scan, in a different place or way, you do not need to use it. The piece of code at your Q2 is just an example of what spring is able to do.

于 2017-02-08T12:07:11.820 回答