Bootstrap

Spring Boot Bean加载顺序

简介

SpringBoot提供了自动加载的机制,老版本中,在classpath目录下新建META-INF/spring.factories文件,便可由SpringFactoriesLoader类完成加载:

#META-INF/spring.factories
org.springframework.boot.env.EnvironmentPostProcessor=\
  com.baomidou.mybatisplus.autoconfigure.SafetyEncryptProcessor
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.baomidou.mybatisplus.autoconfigure.IdentifierGeneratorAutoConfiguration,\
  com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration,\
  com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration

新版本中,需要在classpath目录下新建META-INF/spring/%s.imports文件,由ImportCandidates类完成加载:

#META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.baomidou.mybatisplus.autoconfigure.IdentifierGeneratorAutoConfiguration
com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration
com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration

除了这种方式来加载外部自动装配的类之外,SpringBoot还支持其他加载方式,例如@SpringBootApplication内部就有使用@ComponentScan@Import方式来扫描包。

优先级

有些团队内部框架构建较早,并未按照SpringBoot的方式进行改造,而是简单地使用@ComponentScan来扫描包,由于加载优先级的问题,可能使得@ConditionalOnMissingBean等注解达不到想要的效果,SpringBoot在加载Bean时,遵从以下顺序:

  1. @ComponentScan及其子注解扫描的包,该方式在加载类时,按照以下顺序:
  • jar包的加载顺序
  • 同一个jar包内,按照包名称的层级关系加载
  • 同一个包下面,按照类名的字母优先顺序加载
  1. @Import导入的类,多个@Import类按照声明的顺序加载。
  2. @Bean方式声明的类,按照定义的顺序加载。

修改Bean加载顺序

如果不想按照默认加载顺序来加载某个Bean,可以通过以下方式来修改Bean的加载顺序:

  • 在类或者方法上使用@DependsOn("<beanName>"),可以让另一个Bean先被加载到IOC容器中。
  • 显式指定扫描包的顺序,@SpringBootApplication(scanBasePackages={"",""})
;