Java SpringBoot中的配置顺序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/44314418/
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
Order of Configuration in SpringBoot
提问by chinmay
I am trying to understand how beans that we make using @Configuration
tends to override the beans that are generated by SpringBoot by default. I have been working on a project where in many cases we create beans for things like ZuulConfigs and the assumption is, whatever we are making shall take precedence over the default generated bean. I have been trying to figure this out but can't. Basically,
我试图了解我们使用@Configuration
的 bean如何覆盖默认情况下由 SpringBoot 生成的 bean。我一直在从事一个项目,在许多情况下,我们为 ZuulConfigs 之类的东西创建 bean,并且假设我们所做的一切都应优先于默认生成的 bean。我一直试图弄清楚这一点,但不能。基本上,
- Is Spring achieving this via some custom class loader
- If not how is this precedence working. Can I give some precedence in similar manner to my beans
- Can I generate similar hierarchy in my project,if so how
- Spring 是通过一些自定义类加载器实现的吗
- 如果不是,这个优先级是如何工作的。我可以以类似的方式给我的豆子一些优先权吗
- 我可以在我的项目中生成类似的层次结构吗,如果可以,如何
The help is highly appreciated
非常感谢您的帮助
回答by virsha
Spring AutoConfiguration is used to provide a basic configuration if certain classes are in the classpath or not.
如果某些类是否在类路径中,Spring AutoConfiguration 用于提供基本配置。
If you want to configure the order in which beans are instantiated by spring you can use
如果要配置 spring 实例化 bean 的顺序,可以使用
@DependsOn("A")
public class B {
...
}
This would create bean "A", then "B". Hence you can order the configuration depending upon the beans need first to be done. Anyways Spring automatically detects the dependencies by analyzing the bean classes. for more help check this question Spring Boot AutoConfiguration Order
这将创建bean“A”,然后是“B”。因此,您可以根据首先需要完成的 bean 来订购配置。无论如何,Spring 通过分析 bean 类自动检测依赖项。如需更多帮助,请查看此问题 Spring Boot AutoConfiguration Order
Alternative : There is also "@AutoConfigureOrder" annotation(where you can prioritise the configuration), you can have a look in the codefor deeper understanding.
另一种选择:还有“@AutoConfigureOrder”注解(可以优先配置),可以查看代码更深入的理解。
Documentation of AutoConfiguration is here
AutoConfiguration 的文档在这里
回答by Darshan Mehta
First of all, class loading and bean creation are two different things. We don't need to create a bean to load a class, however, a class has to be loaded in order to create a bean.
首先,类加载和bean创建是两件不同的事情。我们不需要创建一个 bean 来加载一个类,但是,为了创建一个 bean,必须加载一个类。
Now, coming back to Spring's example, Spring looks into all the packages configured by @componentScan
and creates beans of all the classes annotated with @Bean
, @Configuration
and/or @Component
. Spring's container keeps track of all the beans created and hence, when it encounters user defined bean with same name and class type as default bean, it replaces the original definition with user defined one (e.g. we can create our custom @ObjectMapper
to override Spring boot's own instance). You can also use @Primary
annotation to make you bean take precedence if another definition with same class exists (documentation here).
现在,回到 Spring 的示例,Spring 查看由,和/或@componentScan
注释的所有类配置的所有包并创建 bean 。Spring 的容器会跟踪所有创建的 bean,因此,当它遇到与默认 bean 具有相同名称和类类型的用户定义 bean 时,它用用户定义的替换原始定义(例如,我们可以创建我们的自定义来覆盖 Spring boot 自己的实例)。如果存在具有相同类的另一个定义(此处的文档),您还可以使用注释使 bean 优先。@Bean
@Configuration
@Component
@ObjectMapper
@Primary
Below are the answers for your questions:
以下是您的问题的答案:
- Spring uses reflection to load the classes and create instances. Although you can load the classes with your custom class loader (more on that here), you don't need to worry about it for
@Configuration
. - Yes, you can use
@Primary
annotation to give your bean a precedence. You can also use@Order
(here) to define the creation order for your beans. - With
@Primary
,@Order
and@Qualifier
annotationyou can define your own hierarchy for bean creation.
回答by Strelok
Just know this: Spring Boot (specifically) auto configuration classes are always configuredlast. After all user beans have been created. Spring Boot auto configuration classes almost always use the @ConditionalXXXX
annotations to make sure that any beans of the same type/name and other conditions that are configured in your application will take precedence over the Spring Boot auto-configuredbeans.
只要知道这一点:Spring Boot(特别是)自动配置类总是最后配置。在创建了所有用户 bean 之后。Spring Boot 自动配置类几乎总是使用@ConditionalXXXX
注释来确保应用程序中配置的任何具有相同类型/名称和其他条件的 bean 将优先于 Spring Boot自动配置的bean。
回答by Shruti Gupta
If you want your @Component to take precedence over other @Component while scanning all the components by spring, use @Order(Ordered.LOWEST_PRECEDENCE) i.e. the max value to load your component over other.
如果您希望 @Component 在通过 spring 扫描所有组件时优先于其他 @Component,请使用 @Order(Ordered.LOWEST_PRECEDENCE) 即加载您的组件而不是其他组件的最大值。
@Primary is used to give your bean a default preference, we can override the default preference using @Qualifier
@Primary 用于为您的 bean 提供默认首选项,我们可以使用 @Qualifier 覆盖默认首选项
回答by igor.zh
Can I give some precedence in similar manner to my beans
我可以以类似的方式给我的豆子一些优先权吗
Yes.
是的。
A) To define a specific order your Configuration classes will be handled (by the way, a Configuration class does not have to be annotated with @Configuration
(so-called full definition), but it's enough to be annotated with @Component
, @ComponentScan
, @Import
, @ImportResource
or just have a method annotated with @Bean
- so-called lite definition), you should
A) 要定义您的 Configuration 类将被处理的特定顺序(顺便说一句,Configuration 类不必用@Configuration
(所谓的完整定义)注释,但用@Component
, @ComponentScan
,注释就足够了@Import
,@ImportResource
或者只需要一个用@Bean
- 所谓的 lite 定义注释的方法),你应该
1) add your Configuration Candidates to your SpringApplication
's primarySource
, for example, in your main method like that
1)将您的配置候选添加到您的SpringApplication
's primarySource
,例如,在您的主要方法中
SpringApplication.run(
new Class[]{YourSpringBootApplication.class, Config1.class, Config2.class, ...},
args);
2) and annotate each of your Configuration Candidates with @Order
annotation, any other ordering means like Ordered
interface, @DependsOn
etc will be ignored by ConfigurationClassPostProcessor
, the order in the primarySource
array will also be ignored.
2) 并用注释对每个候选配置进行@Order
注释,任何其他排序方式(如Ordered
接口@DependsOn
等)都将被忽略ConfigurationClassPostProcessor
,primarySource
数组中的顺序也将被忽略。
Then ConfigurationClassPostProcessor
will sort your Configuration Candidates and handle them according the @Order
annotation value you specified.
然后ConfigurationClassPostProcessor
将对您的配置候选进行排序并根据@Order
您指定的注释值处理它们。
B) The precedence can also be achieved by defining your own AutoConfiguration classes. Although both Configuration and AutoConfigurationare handled by the same ConfigurationClassPostProcessor
, they are essentially distinctive machineries. To do so
B) 优先级也可以通过定义您自己的 AutoConfiguration 类来实现。尽管Configuration 和 AutoConfiguration由相同的处理方式处理ConfigurationClassPostProcessor
,但它们本质上是不同的机器。这样做
1) define in your classpath /META-INF/spring.factories
file and put in the EnableAutoConfiguration section of it your AutoConfiguration classes like that
1)在你的类路径/META-INF/spring.factories
文件中定义并在它的 EnableAutoConfiguration 部分中放入你的 AutoConfiguration 类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
your.package.AutoConfig1,your.package.AutoConfig2
2) and annotate your AutoConfiguration classes with @AutoConfigureOrder
, @AutoConfigureAfter
, or @AutoConfigureAfter
annotations, any other ordering means again will be ignored.
2),并与注解你自动配置类@AutoConfigureOrder
,@AutoConfigureAfter
或@AutoConfigureAfter
注解,任何其他排序手段再次将被忽略。
Like @Strelok pointed out, AutoConfiguration classes, your own and provided e.g. by spring-boot-autoconfigure
library alike, will be added to the end of the list of Configuration Candidates.
就像@Strelok 指出的那样,您自己的和由spring-boot-autoconfigure
库等提供的 AutoConfiguration 类将被添加到候选配置列表的末尾。
Remember, however, that the order the Configuration Candidateswill be handled by ConfigurationClassPostProcessor
does not necessarily coincide with the order the beansdefined by the Configuration classes will be created. For example, you might define your Configuration class that overrides TomcatServletWebServerFactory
to make your own customization of Tomcat web server like
但是请记住,候选配置的处理ConfigurationClassPostProcessor
顺序不一定与配置类定义的 bean 的创建顺序一致。例如,您可以定义您的 Configuration 类,该类覆盖TomcatServletWebServerFactory
以进行您自己的 Tomcat Web 服务器自定义,例如
@Configuration
public class EmbeddedTomcatConfig {
@Bean
public TomcatServletWebServerFactory containerFactory() {
...
return customizedTomcatWebServerFactory;
}
but this method will be called right at the moment when your Spring Boot application decides to create a Web server, regardless of how you defined the precedence for your EmbeddedTomcatConfig
Configuration class.
但是这个方法会在你的 Spring Boot 应用程序决定创建一个 Web 服务器的那一刻被调用,不管你如何定义你的EmbeddedTomcatConfig
Configuration 类的优先级。
Is Spring achieving this via some custom class loader
Spring 是通过一些自定义类加载器实现的吗
There is no need to. Although you could, as always with Spring, define your own ClassLoader
for BeanFactory
, standard ClassLoader
is good enough if everything you need for Configuration in your application is available in the classpath. Please notice, that at first phase ConfigurationClassPostProcessor
does not load(i.e. does not resolve) the Configuration candidates classes (otherwise, most of the classes in spring-boot-autoconfigure
library will fail to load). Instead it analyzes their annotations with bytecode analyzer, ASM
by default. For that purpose, it is just enough to get a binary form, a byte array, of a class to feed it to bytecode analyzer.
没有必要。尽管您可以像往常一样使用 Spring 定义自己的ClassLoader
for BeanFactory
,但ClassLoader
如果您的应用程序中的 Configuration 所需的一切都在类路径中可用,那么标准就足够了。请注意,第一阶段ConfigurationClassPostProcessor
不加载(即不解析)配置候选类(否则,spring-boot-autoconfigure
库中的大多数类将无法加载)。相反,它ASM
默认使用字节码分析器分析它们的注释。为此,获取一个类的二进制形式,一个字节数组,将其提供给字节码分析器就足够了。