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
@ComponentScan with multiple configuration class : Annotation Based Configuration
提问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 @component
bean in spring container-
在我的 spring web 应用程序中,有多个文件被标记@Configuration
,以便@component
在 spring 容器中注册bean-
Question1-Can we use @ComponentScan
in anyof the @Configuration
class or in all@Configuration
classes?
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 @ComponentScan
is to scan and register stereo type bean(ex- @componant
,@Controller
,@Services
etc..),why we are registering @Configuration
Bean.
编辑:基本上我用理解@ComponentScan
是:扫描并注册立体式豆(EX- @componant
,@Controller
,@Services
等..),为什么我们正在注册@Configuration
的Bean。
采纳答案by TheCurious
For your Question 1 -
对于您的问题 1 -
yes, you can register a bean using @ComponentScan
in any of theconfiguration bean which is registered in spring container.you can register a bean into container by any of the following way-
是的,您可以使用@ComponentScan
在spring 容器中注册的任何配置 bean来注册 bean。您可以通过以下任何一种方式将 bean 注册到容器中 -
- Use
@Configuration
to register bean inrootcontext
ordispatchersevletcontext
. - Import a class in any
@Configuration
bean (which is already registered in container).
- 用于
@Configuration
在rootcontext
或 中 注册 beandispatchersevletcontext
。 - 在任何
@Configuration
bean(已经在容器中注册)中导入一个类。
Let say- you have MvcConfig
class in which you are scanning component-
假设 - 您有MvcConfig
正在扫描组件的课程-
@ComponentScan(basePackages = {"xxxx","yyyy","zzzz"})
@Configuration
public class MvcConfig {
....
}
To register MvcConfig
in 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.class
but also all the component classes those are present in the package in which MyConfiguration
defined.
在这里,spring 不仅注册,MyConfiguration.class
而且还注册了MyConfiguration
定义的包中存在的所有组件类。
回答by Tahir Hussain Mir
Solution to Question 1:
Yes, You can use @Componentscan
in 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 basepackage
attribute or basepackageclasses
. These two are same but using basepackageclasses
has 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 basepackageclasses
attribute.
Now coming back to your 2nd question. Why MyConfiguration.class is specified as the value of basepackageclasses
attribute of @Componentscan
?
First of all, let us know this:basepackageclasses
attribute 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 annotationbasepackageclasses
attribute 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 能够做的一个例子。