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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42111094/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 06:22:06  来源:igfitidea点击:

@ComponentScan with multiple configuration class : Annotation Based Configuration

javaspringspring-mvccomponent-scan

提问by

As per Spring Doc-

根据 Spring Doc-

Configures component scanning directives for use with @Configuration classes. Provides support parallel with Spring XML's <context:component-scan>element.

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

In my spring web application there are multiple files those are marked @Configuration,in order to register @componentbean in spring container-

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

Question1-Can we use @ComponentScanin anyof the @Configurationclass or in all@Configurationclasses?

Question1-我们可以使用@ComponentScan任何的的@Configuration或所有@Configuration类?

Question2-

问题2-

Also I seen in spring doc

我也在spring doc中看到

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

Why here scanning for configuration class itself.

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

edit: Basically my understanding with @ComponentScanis to scan and register stereo type bean(ex- @componant,@Controller,@Servicesetc..),why we are registering @ConfigurationBean.

编辑:基本上我用理解@ComponentScan是:扫描并注册立体式豆(EX- @componant@Controller@Services等..),为什么我们正在注册@Configuration的Bean。

采纳答案by TheCurious

For your Question 1 -

对于您的问题 1 -

yes, you can register a bean using @ComponentScanin any of theconfiguration bean which is registered in spring container.you can register a bean into container by any of the following way-

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

  1. Use @Configurationto register bean in rootcontextor dispatchersevletcontext.
  2. Import a class in any @Configurationbean (which is already registered in container).
  1. 用于@Configurationrootcontext或 中 注册 bean dispatchersevletcontext
  2. 在任何@Configurationbean(已经在容器中注册)中导入一个类。

Let say- you have MvcConfigclass in which you are scanning component-

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

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

To register MvcConfigin container you must do-

MvcConfig在容器中注册,您必须执行-

Either

任何一个

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

Or

或者

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

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

For your Question 2 -

对于您的问题 2 -

Here spring is not only registering MyConfiguration.classbut also all the component classes those are present in the package in which MyConfigurationdefined.

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

回答by Tahir Hussain Mir

Solution to Question 1:
Yes, You can use @Componentscanin as many configuraion classes. That is all up to you. It just registers the various annotated classes of some specific packages as beans. So if you have allthe annotated classes component scanned by just using one @Componentscan,that is enough, as all the required beans you wanted has been activated and registered in the DispatcherServlet container.

Solution to Question 2:

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

问题 2 的解决方案:

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

Your question: Why here scanning for configuration class itself?
This @ComponentScan(basePackageClasses = { MyConfiguration.class })is mentioning MyConfiguration.class as example. The question is what does this mean?

There are two ways to componentscan packages either by basepackageattribute or basepackageclasses. These two are same but using basepackageclasseshas two benefits which are:
It is both type-safe and adds IDE support for future refactoring
That simply means, in future, you may rename (via refactor) some of the base backages, and since you have renamed the base packages, you do not need to change @ComponentScan in your configuration classes if you have used basepackageclassesattribute.

Now coming back to your 2nd question. Why MyConfiguration.class is specified as the value of basepackageclassesattribute of @Componentscan?

First of all, let us know this:
basepackageclassesattribute takes string value which represents some marker class. That Marker class tells: Hey! register all the classes which are present in the package in which this class is present, including this class

So, here in your answer, all those classes will be component-scanned which are present in the package in which MyConfiguration.class is present.

Hence, Myconfiguration.class acts as the Configurationclass as well as the markerclass to component scan other classes as well. Which also implies all the annotated classes will get registered which are present in the package in which MyConfiguration.class is present, including MyConfiguration.class as it is annotated with @Configuration annotation

basepackageclassesattribute can have other classes as well, like com.abc.org.Marker.class

Benefit:
So, if you rename packages, there is no problem, as you have marker classes, which help spring find the packages. These marker classes may or may not have any content inside, as it just acts as a marker to find packages.

你的问题:为什么在这里扫描配置类本身?
@ComponentScan(basePackageClasses = { MyConfiguration.class })是以 MyConfiguration.class 为例。问题是这是什么意思?

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

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

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

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

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

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

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

回答by alfcope

From the documentation:

从文档:

Q1:

问题 1:

@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 @ComponentScanannotation:

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

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

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

Q2:

问题 2:

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.

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



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:

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

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:

或使用旧的 xml 样式:

<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.

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

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.

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