1. 目录

[TOC]

2. 说明

springboot 是一个脚手架,主要用于初始化spring相关的配置,以及根据约定的格式快速配置
约定优于配置是其主要思想

3. 依赖分析

4. 源码分析

4.1. 主入口SpringApplication.run()

1
2
3
public static void main(String[] args) {
SpringApplication.run(D7SpringbootSourceApp.class, args);
}

直接进入SpringApplication创建

1
2
3
4
5
6
7
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}

4.2. new SpringApplication(primarySources) 构造SpringApplication

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
//赋值resourceLoader、primarySources,直接设置属性,没啥逻辑
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));

//获取应用类型,是获取SERVLET、REACTIVE、NONE中,默认主要是SERVLET,classpath有REACTIVE的包才会使用REACTIVE
this.webApplicationType = WebApplicationType.deduceFromClasspath();

//设置初始化器 getSpringFactoriesInstances是获取实例的通用方法
// 设置spring上下文初始化器直接通过set方法保存到SpringApplication属性中
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//设置上下文监听器 设置spring上下文监听器直接通过set方法保存到SpringApplication属性中
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//解析主启动类,通过异常栈找到main方法的类
this.mainApplicationClass = deduceMainApplicationClass();
}

4.2.1. getSpringFactoriesInstances() 从spring.factories中获取类并实例化

这里是一个通用方法,通过匹配传入的类匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//SpringApplication.java
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, new Class<?>[] {});
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
//默认从当前线程中获取到ClassLoader
ClassLoader classLoader = getClassLoader();

//获取到Spring.factories中配置类中传入类对应的实现类名
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
//通过构造器创建,注意args,一般为空,要看实例构造器的参数了,里面就不分析了,一看就懂
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
//排序,返回
AnnotationAwareOrderComparator.sort(instances);
return instances;
}

4.2.1.1. SpringFactoriesLoader.loadFactoryNames() 加载需要实例化的名字 spring-core中的方法

这里是spring-core中的方法,原本与springboot无关,这里就分析一下,但是要记住不是springboot的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
//获取到传入的类全名,获取默认的时候用
String factoryTypeName = factoryType.getName();
//加载
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {

//缓存中取,没有曲到再解析并放入缓存,因此第一次没有缓存,后面的就有了缓存
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}

try {
//从所有依赖包的classpath:META-INF/spring.factories中获取到
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
//分析spring.factories取出其中的Properties
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);

//遍历配置并设置到Map中
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
//放入缓存。此时缓存中包含所有spring.factories的配置
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
//......忽略异常
}

4.3. SpringApplication.run()开始初始化 (主要)

前面构造了SpringApplication实例,加入了初始化器和springboot监听器,从这里开始,就开始初始化的过程了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public ConfigurableApplicationContext run(String... args) {
//记录时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();

ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
//这不影响主流程,暂时不分析是啥
configureHeadlessProperty();
//1 获取springboot应用监听器
// 也是从getSpringFactoriesInstances()加载的spring.factories 中获取 SpringApplicationRunListener springappplication监听器
// 主要是getSpringFactoriesInstances()的逻辑,就不分析了
//2 这里的监听器有一个比较特殊的`EventPublishingRunListener`,他会创建spring上下文的监听器来监听spring上下文ApplicationListener的变化,
// 然后里面不同的监听时机发布不同的事件,从而关联到spring的各种监听器
// starting -> ApplicationStartingEvent
// environmentPrepared -> ApplicationEnvironmentPreparedEvent
// contextPrepared -> ApplicationContextInitializedEvent
// contextLoaded -> ApplicationPreparedEvent 同时这里会设置ApplicationContextAware
// started -> ApplicationStartedEvent
// running -> ApplicationReadyEvent
// failed -> ApplicationFailedEvent
SpringApplicationRunListeners listeners = getRunListeners(args);
//SpringApplication监听器监听启动开始
listeners.starting();
try {

//构造参数,设置环境变量,设置环境变量中,
//当环境变量准备好时通知SpringApplication监听器监听环境变量准备好事件 listeners.environmentPrepared(environment);
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
//打印banner
Banner printedBanner = printBanner(environment);

/*
实例化ApplicationContext,根据是Servlet或者是Reactive来确定上下文的类
默认servlet -> org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
这是继承GenericWebApplicationContext->GenericWebApplicationContext->ConfigurableWebApplicationContext
与传统springmvc项目的 XmlWebApplicationContext 继承ConfigurableWebApplicationContext的实现关系不一样,详细差异见下方图片
*/
context = createApplicationContext();

exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);

//准备上下文,填充属性
prepareContext(context, environment, listeners, applicationArguments, printedBanner);

//刷新上下文,这里会扫描BeanDifinition,同时也会实初始化所有的bean到单例容器中,通过BeanPostProcessor扩展出大量的实现来处理
refreshContext(context);

//刷新后的操作,空方法
afterRefresh(context, applicationArguments);

//记录时间
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}

//SpringApplication监听上下文已经启动
listeners.started(context);

//执行应用启动后的ApplicationRunner 和 CommandLineRunner,这两个通常用于应用启动后执行第一次初始化的,防止失败导致应用停止
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}

try {
//SpringApplication监听器监听正在运行
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}

4.3.1. prepareContext()准备上下文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
//设置环境变量
context.setEnvironment(environment);

//设置beanNameGenerator、resourceLoader、conversionService等,比较简单,都是new然后设置
postProcessApplicationContext(context);

//执行初始化器
applyInitializers(context);

//SpringApplication监听器监听上下文已准备好
listeners.contextPrepared(context);

//打印启动类、启动环境 defalut/dev/prod等
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}

//beanFactory在创建上下文的时候就new出来了,DefaultListableBeanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//注册单例bean springApplicationArguments,这个主要提供访问传入的参数
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);

//注册Banner?有啥用啊
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
//配置覆盖
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
//配置懒加载
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
//拿到启动类信息
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");

//开始加载配置信息,会把@SpringBootApplication加载进去
load(context, sources.toArray(new Object[0]));

//上下文加载完成 , 这个时候不包含项目中注解定义的BeanDifinition,项目中的beanDifinition要在包扫描阶段才执行
listeners.contextLoaded(context);
}

spring-web与springboot上下文的差异
spring-web与springboot上下文的差异

4.3.2. AnnotationConfigServletWebServerApplicationContext#refresh 刷新上下文

这里是真正的初始化上下文的阶段,就是spring初始化上下文的流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//AbstractApplicationContext.java
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//准备刷新,AnnotationConfigServletWebServerApplicationContext中设置了BeanFactroy的ID
prepareRefresh();

//拿到BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

//提前设置一些需要的处理器
prepareBeanFactory(beanFactory);

try {
// 基本没干嘛
postProcessBeanFactory(beanFactory);

//执行所有的BeanFactoryPostProcessor方法初始化,spring大多数扩展(包括注解扫描等)都基于此实现的
//springboot 这里会扫描定义的时候扫描出`AutoConfigurationImportSelector`用于扫出自动化配置并加入Bean定义中
invokeBeanFactoryPostProcessors(beanFactory);

// 注册所有的 BeanFactoryProcessor,为容器bean初始化准备(和spring的保持一致见spring)
registerBeanPostProcessors(beanFactory);

// 初始国际化(见spring)
initMessageSource();

// 初始化事件监听器(见spring)
initApplicationEventMulticaster();

// 刷新容器,这里就只处理了 initThemeSource、createWebServer,创建tomcat容器下方分析,其余同spring一样的就不分析了
onRefresh();

// 注册监听器(见spring)
registerListeners();

// 初始化所有单例bean到容器(见spring)
finishBeanFactoryInitialization(beanFactory);

// 注册生命周期Bean,发布上下文完成事件(见spring)
finishRefresh();
}
catch (BeansException ex) {
//......异常相关的处理
throw ex;
}
finally {
resetCommonCaches();
}
}
}

4.3.2.1. invokeBeanFactoryPostProcessors(beanFactory) 执行扩展处理 已经属于spring-context的内容了

执行所有的BeanFactoryProcessor方法初始化,spring大多数扩展(包括注解扫描等 初始化BeanDifinition的)都基于此实现的

原类方法有几层意义不大的,直接跳过去

1
2
3
4
5
6
7
8
9
10
11
12
//AbstractApplicationContext.java
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {

//执行BeanFactoryPostProcessor
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

//添加 LoadTimeWeaverAwareProcessor
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//PostProcessorRegistrationDelegate.java
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();

if (beanFactory instanceof BeanDefinitionRegistry) {
//......省略部分创建对象
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
//......省略部分逻辑,这里执行BeanDefinitionRegistryPostProcessor钩子函数
registryProcessor.postProcessBeanDefinitionRegistry(registry);
}

}

//......省略了大量排序,添加集合等类容
//根据 PriorityOrdered、Ordered、普通分别执行invokeBeanDefinitionRegistryPostProcessors
//因此后续有三个相同的方法,只是currentRegistryProcessors内容不同

//执行初始化BeannDefinitionRegistry,方法也是循环执行,内部就不看了,
//最终调用postProcessor.postProcessBeanDefinitionRegistry(registry);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);


invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

//执行BeanFactoryPostProcessor,这里也一样,根据排序和未排序来
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);

invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}

else {
//这里基本不走
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}

//这里也是一样,根据优先级分别执行,集合的加入清理过程已省略
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
beanFactory.clearMetadataCache();
}
4.3.2.1.1. ConfigurationClassPostProcessor#processConfigBeanDefinitions() 处理配置的bean定义

这个类也比较长,我们只看最主要的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {

//......省略了很多获取List<BeanDefinitionHolder> configCandidates的方法, 主要是传入的主类
List<BeanDefinitionHolder> configCandidates;

// 处理 @Configuration 注解的类
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);

Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
//将类对应的配置信息解析到ConfigurationClassParser中,后续主次那个
parser.parse(candidates);
parser.validate();

Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
//**这里执行加载Bean定义的方法**
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);

candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
//...省略加载子类的,用于循环
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());

// 注册单例bean,供之后使用 Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}

if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
4.3.2.1.2. ConfigurationClassParser 配置类解析器

invokeBeanDefinitionRegistryPostProcessors()这里其中会调用一个非常重要的处理器ConfigurationClassPostProcessor,此类会处理ConfigurationClassParser
ConfigurationClassParser会处理诸如@Component@PropertySourcesComponentScan@ImportResource@Import

@Import就会扫描出springboot中两个重要的类

  • AutoConfigurationImportSelector: 非常重要的扫描器,此类会执行自动配置,通过加载classpath:META-INF/spring.factories中的配置来自动配置;
  • AutoConfigurationPackages.Registrar: 自动扫描包,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//ConfigurationClassParser.java
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {

// 处理带@Component注解的类
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
processMemberClasses(configClass, sourceClass, filter);
}

//处理 @PropertySource 注解
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}

//处理 @ComponentScan 注解
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}

//处理 @Import 我们主要看这里导入
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

// 处理 @ImportResource
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}

//处理 @Bean 方法
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}

// Process default methods on interfaces
processInterfaces(configClass, sourceClass);

return null;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
boolean checkForCircularImports) {

//......忽略一些
//这里利用到了栈,原因是因为后面有processImports的递归操作, this.deferredImportSelectorHandler.handle()内部也会递归调用的操作
this.importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
//属于ImportSelector走这里,我们的AutoConfigurationImportSelector就是走这里
if (candidate.isAssignable(ImportSelector.class)) {
//获取ImportSelector实例
Class<?> candidateClass = candidate.loadClass();
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
if (selector instanceof DeferredImportSelector) {
//AutoConfigurationImportSelector会走这里,执行handler方法
//这个Handler也是奇怪,只是把selector加入到了deferredImportSelectors中,
//最后在外层再执行this.deferredImportSelectorHandler.process() 统一加入到类中
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
else {
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
}
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
//......
}
finally {
this.importStack.pop();
}
}

AutoConfigurationImportSelector 扫描并获取到注解的类

4.3.2.2. onRefresh()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//ServletWebServerApplicationContext.java
protected void onRefresh() {
super.onRefresh();
try {
//创建tomcat容器
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
//创建tomcat容器
private void createWebServer() {
//空的null
WebServer webServer = this.webServer;
//空的null
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
//走这里,创建Servlet工厂,设置值,同tomcat启动的顺序完全相反,这里是上下文加载完成后在启动tomcat
ServletWebServerFactory factory = getWebServerFactory();
this.webServer = factory.getWebServer(getSelfInitializer());
getBeanFactory().registerSingleton("webServerGracefulShutdown",
new WebServerGracefulShutdownLifecycle(this.webServer));
getBeanFactory().registerSingleton("webServerStartStop",
new WebServerStartStopLifecycle(this, this.webServer));
}
//不走
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
initPropertySources();
}

4.4. AutoConfigurationImportSelector 自动配置扫描器

AutoConfigurationImportSelector通过在刷新beanFactory阶段执行invokeBeanFactoryPostProcessors从而调起ConfigurationClassPostProcessor->ConfigurationClassParser->处理@Import,@Import会扫描到配置类

5. 总结

5.1. SpringApplication.run启动方法比较简单

  • 初始化初始化器和监听器
  • 准备环境变量
  • 创建上下文
  • 初始化上下文信息
  • 刷新上下文(这里面利用context.refresh方法,刷新工厂,创建beandifinition,利用扩展BeanDifinitionRegistryProcessor和BeanPostProcessor扩展应用内的注解,包括@SpringBootApplication等)
    • 准备刷新
    • 设置beanFactory
    • 提前设置一些需要bean
    • 执行BeanFactoryPostProcessors扩展,这里会加载BeanDifinition
    • 初始化BeanPostProcessors
    • 初始化事件发布器
    • 准备刷新(初始化tomcat)
    • 注册监听器
    • 执行容器初始化
    • 完成刷新
  • 完成启动

5.2. @SprinBbootApplication 很难

主要是子注解@EnableAutoConfiguration

主要在上下文刷新里面的执行BeanFactoryPostProcessors扩展时通过ConfigurationClassPostProcessor调用ConfigurationClassParser扫描@Import注解,从而扫描到AutoConfigurationImportSelector
通过AutoConfigurationImportSelector扫描自动配置类并在ConfigurationClassPostProcessor注册BeanDifinition

具体的怎么通过@ImportAutoConfigurationImportSelector并将配置类加入到ConfigurationClassParser中就不知道了,执行是直接执行ConfigurationClassParser收集到的信息;

6. 注意事项