SpringBoot的項目啟動類只有一個注解@SpringBootApplication和一個run方法。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
直接點進@SpringBootApplication
@SpringBootApplication:
包含了@SpringBootConfiguration(打開是@Configuration),
@EnableAutoConfiguration,
@ComponentScan注解。
@Configuration
這里的啟動類標注了@Configuration之后,本身其實也是一個IoC容器的配置類。任何一個標注@Configuration的Java類定義都是一個JavaConfig配置類。任何一個標注了@Bean的方法,其返回值將作為一個bean定義注冊到Spring的IoC容器,方法名將默認成該bean定義的id。
@ComponentScan
@ComponentScan的功能其實就是自動掃描並加載符合條件的組件(比如@Component和@Repository等)或者bean定義,最終將這些bean定義加載到IoC容器中。可以通過basePackages等屬性來細粒度的定制@ComponentScan自動掃描的范圍如果不指定,則默認Spring框架實現會從聲明@ComponentScan所在類的package進行掃描。
@EnableAutoConfiguration
最關鍵的是@Import的幫助,將所有符合自動配置條件的bean定義加載到IoC容器。該配置模塊的主要使用到了SpringFactoriesLoader。
SpringFactoriesLoader詳解
SpringFactoriesLoader為Spring工廠加載器,該對象提供了loadFactoryNames方法,入參為factoryClass和classLoader即需要傳入工廠類名稱和對應的類加載器,方法會根據指定的classLoader,加載該類加器搜索路徑下的指定文件,即spring.factories文件,傳入的工廠類為接口,而文件中對應的類則是接口的實現類,或最終作為實現類。獲取到這些實現類的類名后,loadFactoryNames方法返回類名集合,方法調用方得到這些集合后,再通過反射獲取這些類的類對象、構造方法,最終生成實例。
AutoConfigurationImportSelector
該類主要關注selectImports方法
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
該方法在springboot啟動流程——bean實例化前被執行,返回要實例化的類信息列表。如果獲取到類信息,spring可以通過類加載器將類加載到jvm中,現在我們已經通過spring-boot的starter依賴方式依賴了我們需要的組件,那么這些組件的類信息在select方法中就可以被獲取到。
其中最重要的是getAutoConfigurationEntry里邊調用了getCandidateConfigurations方法
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
其返回一個自動配置類的類名列表,方法調用了loadFactoryNames方法,查看該方法
public static List<String> loadFactoryNames(Class<?> factoryType,
自動配置器會跟根據傳入的factoryClass.getName()到項目系統路徑下所有的spring.factories文件中找到相應的key,從而加載里面的類。