SpringBoot中的配置顺序

时间:2017-06-01 18:13:14

标签: java spring spring-boot

我试图了解我们使用@Configuration生成的bean如何覆盖默认情况下由SpringBoot生成的bean。我一直致力于一个项目,在很多情况下我们为像ZuulConfigs这样的东西创建bean,并且假设是,无论我们做什么,都应优先于默认生成的bean。我一直试图解决这个问题,但不能。基本上,

  1. Spring是通过一些自定义类加载器实现的吗
  2. 如果不是,这个优先级如何工作。我能否以与我的豆类似的方式给予一些优先权
  3. 我可以在项目中生成类似的层次结构,如果是这样的话
  4. 非常感谢帮助

5 个答案:

答案 0 :(得分:5)

如果某些类在类路径中,则使用Spring AutoConfiguration提供基本配置。

如果要配置spring实例化bean的顺序,可以使用

@DependsOn("A") 
 public class B {
 ...    
}

这会创建bean“A”,然后是“B”。因此,您可以根据首先需要完成的bean来订购配置。无论如何Spring通过分析bean类自动检测依赖关系。 如需更多帮助,请查看此问题 Spring Boot AutoConfiguration Order

替代方案: 还有“@AutoConfigureOrder”注释(您可以在其中优先配置),您可以查看code以获得更深入的理解。

自动配置的文档是here

答案 1 :(得分:2)

首先,类加载和bean创建是两回事。我们不需要创建一个bean来加载一个类,但是,为了创建一个bean,必须加载一个类。

现在,回到Spring的示例,Spring查看@componentScan配置的所有包,并创建所有使用@Bean@Configuration和/或{{1}注释的类的bean }}。 Spring的容器跟踪创建的所有bean,因此,当它遇到与默认bean具有相同名称和类型的用户定义bean时,它将用用户定义的bean替换原始定义(例如,我们可以创建自定义@Component到覆盖Spring引导自己的实例)。如果存在具有相同类的另一个定义(文档here),您还可以使用@ObjectMapper注释使bean优先。

以下是您的问题的答案:

  1. Spring使用反射加载类并创建实例。虽然您可以使用自定义类加载器加载类(here上的更多内容),但您无需担心@Primary
  2. 是的,您可以使用@Configuration注释为您的bean提供优先权。您还可以使用@Primaryhere)来定义Bean的创建顺序。
  3. 使用@Order@Primary@Order annotation,您可以为bean创建自己的层次结构。

答案 2 :(得分:2)

请注意:Spring Boot(特别是)自动配置类始终配置。在创建所有用户bean之后。 Spring Boot自动配置类几乎总是使用@ConditionalXXXX注释来确保应用程序中配置的相同类型/名称和其他条件的任何bean都优先于Spring Boot 自动配置< / em>豆。

答案 3 :(得分:1)

  

我可以用与我的豆子相似的方式赋予某些优先级

是的。

A)要定义特定的顺序,将处理您的配置类(顺便说一句,不必对配置类进行@Configuration注释(所谓的完整定义),但足以对其进行注释与@Component@ComponentScan@Import@ImportResource一起使用,或者只是用@Bean注释的方法-所谓的lite定义),您应该

1)例如,以这样的主要方法将您的配置候选者添加到SpringApplication的{​​{1}}中

primarySource

2)并用SpringApplication.run( new Class[]{YourSpringBootApplication.class, Config1.class, Config2.class, ...}, args); 注释您的每个配置候选者,@Order将忽略Ordered接口,@DependsOn等的任何其他排序方式,该命令ConfigurationClassPostProcessor数组中的内容也将被忽略。

然后primarySource将对您的配置候选进行排序并根据您指定的ConfigurationClassPostProcessor注释值进行处理。

B)优先级也可以通过定义自己的AutoConfiguration类来实现。尽管配置和自动配置都由相同的@Order处理,但它们本质上是与众不同的机器。这样做

1)在类路径ConfigurationClassPostProcessor文件中定义,然后将您的AutoConfiguration类放入该文件的EnableAutoConfiguration部分

/META-INF/spring.factories

2)并使用 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ your.package.AutoConfig1,your.package.AutoConfig2 @AutoConfigureOrder@AutoConfigureAfter注释注释您的AutoConfiguration类,其他任何排序方式都将被忽略。

就像@Strelok指出的那样,AutoConfiguration类是您自己的,并提供了例如由@AutoConfigureAfter库提供的,将被添加到“配置候选人”列表的末尾。

但是请记住,配置候选者的顺序将由spring-boot-autoconfigure处理。不一定与配置类定义的bean的顺序一致将被创建。例如,您可以定义覆盖ConfigurationClassPostProcessor的Configuration类来对Tomcat Web服务器(如

)进行自定义
TomcatServletWebServerFactory

但是,无论您如何定义@Configuration public class EmbeddedTomcatConfig { @Bean public TomcatServletWebServerFactory containerFactory() { ... return customizedTomcatWebServerFactory; } 配置类的优先级,该方法都会在Spring Boot应用程序决定创建Web服务器时立即调用。

  

Spring是否通过某些自定义类加载器实现了这一目标

没有必要。尽管您可以像使用Spring一样为EmbeddedTomcatConfig定义自己的ClassLoader,但如果在类路径中可以使用应用程序中配置所需的所有内容,则标准BeanFactory就足够了。请注意,在第一阶段ClassLoader不会 load (即不 resolve )配置候选类(否则,{{1中的大多数类}}库将无法加载)。相反,它默认使用字节码分析器ConfigurationClassPostProcessor分析它们的注释。为此,只需将一个类的二进制形式(字节数组)馈送到字节码分析器就足够了。

答案 4 :(得分:0)

如果要让@Component在春季扫描所有组件时优先于其他@Component,请使用@Order(Ordered.LOWEST_PRECEDENCE),即最大值,以将您的组件加载到其他组件上。

@Primary用于为您的bean提供默认首选项,我们可以使用@Qualifier覆盖默认首选项