springboot相關(guān)邏輯
1. main啟動(dòng)類
首先就是springboot項(xiàng)目習(xí)以為常的main方法調(diào)用SpringApplication.run將標(biāo)注有@SpringBootApplication注解的class對(duì)象作為參數(shù)傳遞。SpringBootApplication注解是個(gè)組合注解,主要組合了@Configuration
,@EnableAutoConfiguration
,@Import(AutoConfigurationImportSelector.class)
, @ComponentScan
等關(guān)鍵注解司训。
@SpringBootApplication
public class SampleWebUiApplication {
public static void main(String[] args) {
SpringApplication.run(SampleWebUiApplication.class, args);
}
}
2. 調(diào)用SpringApplication構(gòu)造函數(shù)
通過第一步調(diào)用靜態(tài)方法run,內(nèi)部轉(zhuǎn)換為實(shí)例化SpringApplication并調(diào)用實(shí)例方法run。
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
/**
* 通過getSpringFactoriesInstances 方法從META-INF/spring.factories文件中獲取所有ApplicationContextInitializer 回調(diào)接口踪少,
* 用于在刷新之前初始化Spring ConfigurableApplicationContext。
* 通常在需要對(duì)應(yīng)用程序上下文進(jìn)行一些編程初始化的Web應(yīng)用程序中使用糠涛。
* 例如援奢,注冊(cè)屬性源或針對(duì)上下文環(huán)境激活配置文件。
* 有關(guān)分別聲明“ contextInitializerClasses”上下文參數(shù)和初始化參數(shù)的信息忍捡,請(qǐng)參見ContextLoader和FrameworkServlet支持集漾。
* 鼓勵(lì)A(yù)pplicationContextInitializer處理器檢測(cè)是否已實(shí)現(xiàn)Spring的Ordered接口,或者是否存在@Order注釋砸脊,并在調(diào)用之前對(duì)實(shí)例進(jìn)行相應(yīng)的排序具篇。
*/
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
SpringApplication#getSpringFactoriesInstances
從"META-INF/spring.factories"中加載并實(shí)例化給定類型的所有實(shí)現(xiàn)類
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
// 使用給定的類加載器從“META-INF/spring.factories”中加載給定類型的所有實(shí)現(xiàn)類全限定名。
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 通過反射實(shí)例化所有從上面獲取的全限定類名
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
3. 調(diào)用SpringApplication實(shí)例對(duì)象的run方法
SpringApplication#run
...... 忽略部分代碼
try {
...
// 1. 通過反射實(shí)例化ApplicationContext
// 2. 實(shí)例化applicationContext時(shí)調(diào)用其無參構(gòu)造函數(shù)實(shí)例化AnnotatedBeanDefinitionReader凌埂,ClassPathBeanDefinitionScanner
// 3. 實(shí)例化AnnotatedBeanDefinitionReader時(shí)構(gòu)造函數(shù)通過AnnotationConfigUtils.registerAnnotationConfigProcessors注冊(cè)一些內(nèi)部必要的BeanDefinition
// 如 ConfigurationClassPostProcessor(處理@Configuration @Import等注解), AutowiredAnnotationBeanPostProcessor(自動(dòng)注入)等驱显。
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[]{ConfigurableApplicationContext.class}, context);
// 1. 調(diào)用從spring.factories加載的
// 2. 加載primarySources以及sources到BeanDefinition(用于解析@SpringBootApplication,通過ConfigurationClassPostProcessor)
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 1. 調(diào)用AbstractApplicationContext#refresh方法
// 2. 通過調(diào)用invokeBeanFactoryPostProcessors方法調(diào)用ConfigurationClassPostProcessor處理primarySources類的注解
// 3. ConfigurationClassPostProcessor處理@SpringBootApplication的元注解@ComponentScan掃描包組件注冊(cè)到BeanDefinitionRegistry
// 4. ConfigurationClassPostProcessor通過@EnableAutoConfiguration的元注解@Import中的AutoConfigurationImportSelector自動(dòng)導(dǎo)入spring.factories中的類到BeanDefinitionRegistry
// 5.啟動(dòng)內(nèi)置web容器(調(diào)用ServletWebServerApplicationContext#onRefresh)
refreshContext(context);
afterRefresh(context, applicationArguments);
...
} catch (Throwable ex) {
...
}
try {
listeners.running(context);
} catch (Throwable ex) {
...
}
return context;
SpringApplication#createApplicationContext
用于創(chuàng)建ApplicationContext的策略方法,默認(rèn)情況下,此方法將使用任何明確設(shè)置的應(yīng)用程序上下文或應(yīng)用程序上下文類,然后再使用合適的默認(rèn)值埃疫。
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
//org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
// org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
// org.springframework.context.annotation.AnnotationConfigApplicationContext
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
} catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
}
}
// 通過反射實(shí)例化context,在對(duì)應(yīng)ApplicationContext的構(gòu)造方法中實(shí)例化{@link AnnotatedBeanDefinitionReader
// 并在該reader的構(gòu)造方法中通過{@link AnnotationConfigUtils#registerAnnotationConfigProcessors}
// 注冊(cè)一些內(nèi)部必要的BeanDefinition如:{@link ConfigurationClassPostProcessor},{@link AutowiredAnnotationBeanPostProcessor}等
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
上訴方法最后一步反射實(shí)例化應(yīng)用上下文時(shí)伏恐,很關(guān)鍵的一步就是向容器中注冊(cè)一些非常重要的的BeanDefinition(如:ConfigurationClassPostProcessor
,AutowiredAnnotationBeanPostProcessor
等)栓霜,主要步驟:AnnotationConfigServletWebServerApplicationContext()
-> new AnnotatedBeanDefinitionReader
-> AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)
AnnotationConfigUtils.registerAnnotationConfigProcessors
注冊(cè)spring內(nèi)部必要的一些beanDefinition
···
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// 在Spring#refresh時(shí)調(diào)用invokeBeanFactoryPostProcessors(beanFactory)方法時(shí)調(diào)用翠桦,用來處理@Configuration @Import等注解
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
// CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
...
下圖斷點(diǎn)為createApplicationContext
方法執(zhí)行結(jié)束后,beanDefinitionMap中的內(nèi)容
SpringApplication#prepareContext
準(zhǔn)備上下文
...
// 調(diào)用從spring.factories獲取的ApplicationContextInitializer
applyInitializers(context);
...
// 獲取所有資源胳蛮,如在main方法中傳進(jìn)來的SampleWebUiApplication.class等
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
// 將資源注冊(cè)為BeanDefinition
load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
下圖斷點(diǎn)為prepareContext
方法執(zhí)行結(jié)束后销凑,beanDefinitionMap中的內(nèi)容
SpringApplication#refreshContext
刷新上下文具體如下。
spring refresh之invokeBeanFactoryPostProcessors
調(diào)用ConfigurationClassPostProcessor整體流程圖
AbstractApplicationContext#refresh
......
// 調(diào)用實(shí)現(xiàn)BeanFactoryPostProcessor的后置處理器仅炊,
// 其實(shí)就是在上述new AnnotatedBeanDefinitionReader時(shí)注冊(cè)的解析配置類的后置處理器ConfigurationClassPostProcessor
// 這里主要解析SpringBootApplication元注解中的Import注解以及ComponentScan注解等斗幼。
invokeBeanFactoryPostProcessors(beanFactory);
......
AbstractApplicationContext#invokeBeanFactoryPostProcessors
//由于之前注冊(cè)的都是BeanDefinition,此時(shí)還并沒有生產(chǎn)任何的BeanFactoryPostProcessor,所以getBeanFactoryPostProcessors是空的
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors
從beanDefinitionMap中獲取實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor接口的實(shí)現(xiàn)類茂洒,并調(diào)用
//放置已處理的beanName
Set<String> processedBeans = new HashSet<>();
//放置常規(guī)的后置處理器孟岛,就是只實(shí)現(xiàn)了BeanFactoryPostProcessor接口的
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//放置實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor接口的,之前我們注冊(cè)的后置處理器中只有ConfigurationClassPostProcessor實(shí)現(xiàn)了
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
//放置當(dāng)前的RegistryProcessors
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
//查找實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor接口的BeanName,其實(shí)目前就只有一個(gè)ConfigurationClassPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
//ConfigurationClassPostProcessor同樣實(shí)現(xiàn)了PriorityOrdered接口
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//調(diào)用了getBean方法督勺,產(chǎn)生了ConfigurationClassPostProcessor實(shí)例,放到currentRegistryProcessors集合中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
//排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
//將實(shí)例化出來的后置處理器放到集合中
registryProcessors.addAll(currentRegistryProcessors);
// 調(diào)用ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//清空渠羞,以便處理后面的后置處理器
currentRegistryProcessors.clear();
//再次查找實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor接口的BeanName,這里就是可能就是從配置類中解析出來的一些
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
//不包括已經(jīng)處理過的智哀,并且先處理實(shí)現(xiàn)Ordered接口的
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
//根據(jù)Ordered排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
//將后置處理器放到已注冊(cè)的集合中
registryProcessors.addAll(currentRegistryProcessors);
//調(diào)用所有后置處理器的postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//再次清理次询,因?yàn)楹竺孢€要處理未實(shí)現(xiàn)Ordered接口的
currentRegistryProcessors.clear();
......
ConfigurationClassPostProcessor#processConfigBeanDefinitions
處理@Configuration注解以及相關(guān)的@Bean,@Import等注解
//放置候選配置類
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
//遍歷之前注冊(cè)的所有bean定義,找到其中的配置類瓷叫,其實(shí)就是我們自己傳進(jìn)來的配置類
for (String beanName : candidateNames) {
//...省略校驗(yàn)過程...
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//檢查是否是有@Configuration注解的BeanDifinition -> full類型的配置類 -> 會(huì)把配置類替換成動(dòng)態(tài)代理類
//或者該類包含@Component @ComponentScan @Import @ImportResource @Bean 注解的其中之一 -> lite類型的配置類 -> 不會(huì)替換成動(dòng)態(tài)代理類
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
//....省略片段....
//實(shí)例化一個(gè)配置類解析器
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
do {
//解析配置類
parser.parse(candidates);
parser.validate();
//parser.getConfigurationClasses()就是拿到剛剛解析完放到map中的配置類
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
//這里處理@Import導(dǎo)入的beanDefintion和配置類中的@Bean
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
//以下邏輯是找出未解析的配置類屯吊,如@Bean和ImportBeanDefinitionRegistrar所引入的
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
//將是配置類并且沒有解析過的BeanDefinition放到候選集合中繼續(xù)解析
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
ConfigurationClassUtils.checkConfigurationClassCandidate
檢查給定的bean定義是否是配置類(或在配置類/組件類中聲明的嵌套類,也要自動(dòng)注冊(cè))摹菠,并進(jìn)行相應(yīng)標(biāo)記盒卸。
...
//檢查是否有標(biāo)識(shí)@Configuration
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
//設(shè)置配置屬性值為full
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
//檢查是否包含@Component @ComponentScan @Import @ImportResource @Bean
else if (config != null || isConfigurationCandidate(metadata)) {
//設(shè)置配置屬性值為lite
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}
經(jīng)過checkConfigurationClassCandidate
后,此時(shí)容器中只有啟動(dòng)類屬于配置類次氨,進(jìn)行解析的只有該類蔽介,當(dāng)然后續(xù)還有解析出來的其他配置類會(huì)在while里繼續(xù)解析
ConfigurationClassParser#parse
配置類解析流程
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
// 配置類的beanDefinition為AnnotatedGenericBeanDefinition
if (bd instanceof AnnotatedBeanDefinition) {
//傳入配置類的元數(shù)據(jù)與beanName
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
......
}
// 處理實(shí)現(xiàn)了DeferredImportSelector接口的實(shí)現(xiàn)類,用來延遲處理@Import
// @EnableAutoConfiguration注解導(dǎo)入的AutoConfigurationImportSelector就屬于該類型
this.deferredImportSelectorHandler.process()
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}
ConfigurationClassParser#processConfigurationClass
...
SourceClass sourceClass = asSourceClass(configClass, filter);
do {
//解析配置類煮寡,這里可能返回配置類的父類虹蓄,需要繼續(xù)處理
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
while (sourceClass != null);
//將配置類放入map中
this.configurationClasses.put(configClass, configClass);
ConfigurationClassParser#doProcessConfigurationClass
......
//@Configuration 本身也是 @Component的組合注解
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// 處理內(nèi)置類,如果內(nèi)置類也是個(gè)配置類幸撕,遞歸處理內(nèi)置類
processMemberClasses(configClass, sourceClass, filter);
}
// Process any @ComponentScan annotations
// 找出配置類上的@ComponentScan注解屬性
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
for (AnnotationAttributes componentScan : componentScans) {
//將@ComponentScan引入的所有類掃描成BeanDefinition并注冊(cè)到容器中
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
//這里循環(huán)是為了判斷掃描出來的beanDefinition是否是配置類薇组,如果是配置類的話需要遞歸解析
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
//這里是必然為true, 能被掃描出來的必然有@Component注解,而@Component注解為lite配置類
//這里主要是為了在檢查的同時(shí)設(shè)置一下full或者lite的類型
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
//配置類就繼續(xù)遞歸解析
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
// 處理@Import注解
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
...
// 將配置類中@Bean的方法解析成方法元數(shù)據(jù)放到配置類中
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
...
ConfigurationClassParser#processImports
處理@Import注解
//importCandidates為@Import中的value數(shù)組
for (SourceClass candidate : importCandidates) {
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
//實(shí)例化我們寫的實(shí)現(xiàn)ImportSelector接口的類
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);
if (selector instanceof DeferredImportSelector) {
// 如果是實(shí)現(xiàn)了延遲導(dǎo)入坐儿,則用延遲導(dǎo)入方式導(dǎo)入
// 將其加入到deferredImportSelectors數(shù)組中律胀,待全部處理完后在ConfigurationClassParser#parse方法最后進(jìn)行處理導(dǎo)入
// @EnableAutoConfiguration注解導(dǎo)入的AutoConfigurationImportSelector就屬于該類型
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
} else {
//調(diào)用selectImports方法返回我們需要注入到容器中bean數(shù)組
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
//轉(zhuǎn)為SourceClass集合
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
//再次遞歸調(diào)用本方法宋光,如果我們返回的數(shù)組是一些沒有實(shí)現(xiàn)Import相關(guān)接口的類,
//就會(huì)走到最后的else邏輯炭菌,當(dāng)成配置類處理
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
}
//這里就走實(shí)現(xiàn)ImportBeanDefinitionRegistrar接口的邏輯
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
//實(shí)例化
ImportBeanDefinitionRegistrar registrar =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
this.environment, this.resourceLoader, this.registry);
//這里先把Registrar放到配置類的importBeanDefinitionRegistrars屬性中跃须,最后解析完調(diào)用loadBeanDefinition進(jìn)行處理
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
//普通的bean當(dāng)做配置類處理
processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
}
處理完上述方法后回到ConfigurationClassParser#parse
的最后一步處理DeferredImportSelector接口實(shí)現(xiàn)類(this.deferredImportSelectorHandler.process()
),調(diào)用ConfigurationClassParser.DeferredImportSelectorGroupingHandler#processGroupImports
ConfigurationClassParser.DeferredImportSelectorGrouping#getImports
獲取DeferredImportSelector導(dǎo)入的條目
for (DeferredImportSelectorHolder deferredImport : this.deferredImports {
// 調(diào)用AutoConfigurationImportSelector.AutoConfigurationGroup#process獲取需要自動(dòng)導(dǎo)入的配置類
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
return this.group.selectImports();
AutoConfigurationImportSelector.AutoConfigurationGroup#process
獲取需要自動(dòng)導(dǎo)入的配置類信息
// 從META-INFO/spring.factories文件下獲取EnableAutoConfiguration對(duì)應(yīng)的配置類列表
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(annotationMetadata);
this.autoConfigurationEntries.add(autoConfigurationEntry);
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
AutoConfigurationImportSelector#getAutoConfigurationEntry
...
// 從META-INFO/spring.factories文件下獲取EnableAutoConfiguration對(duì)應(yīng)的配置類列表
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
// 從META-INFO/spring.factories文件下獲取org.springframework.boot.autoconfigure.EnableAutoConfiguration對(duì)應(yīng)的配置類列表
// getSpringFactoriesLoaderFactoryClass() -> EnableAutoConfiguration.class
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), 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;
}
執(zhí)行完getCandidateConfigurations獲取到的配置列表
最后回到ConfigurationClassPostProcessor#processConfigBeanDefinitions
方法中的的this.reader.loadBeanDefinitions(configClasses)
將解析出來的類注冊(cè)到beanDefinitionMap娃兽,之后在refresh的finishBeanFactoryInitialization
方法中實(shí)例化這些bean。