读完这章,你还敢说你不会SpringBoot源码?

前言

笔者把之前的Spring的格式重新排版,并且细致到一行一个讲解,希望大家喜欢。

大家使用Spring Boot这么久了,有没有知道Spring Boot的启动流程是怎样的呢?Spring是如何扫描到使用@Component的类并且把它放进BeanFactory呢?它是如何启动的呢?现在我们就一起看看。本系列会分几个章节去讲述这个Spring Boot的启动过程。由于写这篇文章的时候,在很多环境写过,所以可能由于Spring Boot版本不同代码也不同,但是思路是一样的。

1.创建SpringApplication对象

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
java复制代码// 1.main方法
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class DemoApplication {

public static void main(String[] args) {
// 启动入口,请点击run方法
SpringApplication.run(DemoApplication.class, args);
}
}
// 2.main方法进来后先创建一个实例new SpringApplication 蹩脚翻译一下
/**
* 创建一个新的SpringApplication实例也就是要new SpringApplication(),并且定义主要的类作为Bean的加载来源
*/
/**
* Create a new {@link SpringApplication} instance. The application context will load
* beans from the specified primary sources (see {@link SpringApplication class-level}
* documentation for details. The instance can be customized before calling
* {@link #run(String...)}.
* @param resourceLoader the resource loader to use
* @param primarySources the primary bean sources
* @see #run(Class, String[])
* @see #setSources(Set)
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
// 设置类入口也就是启动类
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 设置这个应用的类型,分别为SERVLET、NONE、REACTIVE。具体可以看WebApplicationType枚举类
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 设置初始化器,这个getSpringFactoriesInstances()方法是从spring.factories中读取
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 设置监听器,更上面一样也就是只要看到这个方法就是从spring.factories中读取要的类并且加载
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}

2.在SpringApplication对象调用run()

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
java复制代码/**
* 1.跑run方法
*/
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
// 开启计时器
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 配置一些外设
configureHeadlessProperty();
// 获取监听器,这个getRunlisteners方法里面也是一样获取监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
// 监听器开始执行
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
// 打印banner
Banner printedBanner = printBanner(environment);
// 创建应用上下文,请看2
context = createApplicationContext();
// 加载异常报告期
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 准备上下文,请看3
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 刷新上下文
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}

try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
/**
* 2.这个方法是从创建SpringApplication实例加载的应用类型去创建不同的上下文实例,这里由于是SERVLET类型所以会创建
*/
protected ConfigurableApplicationContext createApplicationContext() {
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:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
/**
* 3.准备上下文,这里其实挺重要的,讲述了启动类如何加载到BeanFactory
* 其实就一个重点,在load()这个方法里面
*/
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
postProcessApplicationContext(context);
applyInitializers(context);
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
// 这里context因为是AnnotationConfigServletWebServerApplicationContext
// 所以他继承于ServletWebServerApplicationContext
// ServletWebServerApplicationContext继承GenericWebApplicationContext
// GenericWebApplicationContext继承GenericApplicationContext
// 所以他的beanFactory是默认的private final DefaultListableBeanFactory beanFactory;
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
// 这个方法讲述了启动类如何注册到beanFactory里面,为下面的refreshContext做了铺垫
// 而且这个load方法里面还有启动类如何注册到BeanDefinition里面去的,去看4
load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
/**
* 4.这里就先说下doRegisterBean()
* 每个bean被执行doGetBean方法前都是要把Bean的定义信息拿到,也就是通俗的BeanDefinition,类的元数据
* 而AnnotatedGenericBeanDefinition就是为了公开这些类元数据做的接口
* 当adb和beanName一起在BeanDefinitionHolder初始化的时候
*/
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
// 定义bean的元数据对象,下面都是获取bean名字之类的
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}
// 当元数据对象与beanName创建了BeanDefinitionHolder
// 他会把一些alias和beanName全部保存下来
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 这里就会正式把此bean注册到this.beanDefinitionMap和this.beanDefinitionNames属性里面
// 而这两个属性就是刚刚的默认beanFactory也就是DefaultListableBeanFactory.class
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

3.核心方法refreshContext

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
java复制代码/**
* 1.此方法其实就是Spring整个启动过程或者说ioc等等的核心流程了
* 这个方法分几步去讲解
*/
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 准备上下文
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 这个方法是扫描所有的Bean和加载所有的Bean
invokeBeanFactoryPostProcessors(beanFactory);


// Instantiate all remaining (non-lazy-init) singletons.
// 前面是扫描和加载,这个步骤就是真正的创建Bean实例了
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
finishRefresh();
}

catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}

// Destroy already created singletons to avoid dangling resources.
destroyBeans();

// Reset 'active' flag.
cancelRefresh(ex);

// Propagate exception to caller.
throw ex;
}

finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
/**
* 2.这里进来就是beanFactory增强器加载
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// getBeanFactoryPostProcessors()这个方法就是获取当前所有的beanFactory增强器进去可以看看,目前默认有3个
// 1.SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor在prepareContext中的applyInitializers插入
// 2.ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor在prepareContext中的applyInitializers插入
// 3.ConfigFileApplicationListener$PropertySourceOrderingPostProcessor在prepareContext最后一行listeners.contextLoaded(context)插入
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
/**
* 3.这方法重中之重,里面包涵了大量的操作我们来一起看看
*/
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
// 这个context是AnnotationConfigServletWebServerApplicationContext实例他继承的类有BeanDefinitionRegistry接口
// 所以这里一定会进来
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 这个循环是把那3个增强器分类
// CachingMetadataReaderFactoryPostProcessor实现BeanDefinitionRegistryPostProcessor
// ConfigurationWarningsPostProcesso实现BeanDefinitionRegistryPostProcessor
// PropertySourceOrderingPostProcessor实现BeanFactoryPostProcessor
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
// 这里把BeanDefinition注册进去
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}

// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 这里获取到的beanName不是刚刚的增强器而是常量org.springframework.context.annotation.internalConfigurationAnnotationProcessor
// 并且下面这个循环会把ConfigurationClassPostProcessor加载出来。
// 那么大家会问ConfigurationClassPostProcessor什么时候加载的呢?
// createApplicationContext这个方法还记得吧!就是在这里加载的当Spring选择了Servlet模式就会加载配置
// CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME就会作为beanNamePut进beanFactory
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 当ConfigurationClassPostProcessor回去跑processConfigBeanDefinitions方法,跳去4
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();

// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}

// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}

else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}

// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}

// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
/**
* 4.这里就是把启动类选出来并且开始ComponentScan的地方,自动装配也是这里完成的@Import
*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
//configCandidates这会加入启动类
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
/**
* 省略代码
*/
// Parse each @Configuration class
// 这就是找Component的实现类
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 {
// 这个是重点parse有很多Component类这里用来
parser.parse(candidates);
/**
* 省略代码
*/
}
while (!candidates.isEmpty());
/**
* 省略代码
*/
}
/**
* 5.扫描Component和自动装配,这个也很重要,而且段代码有几个递归也是比较复杂
* 也是希望大家能够自己debug进去看看这到底是如何递归的
*/
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {

/**
* 省略代码
*/
// Process any @ComponentScan annotations
// 这个为什么是数组呢?当你使用@ComponentScans(value = {@ComponentScan("com.example.test"), @ComponentScan("com.example.test1")})
// 这里的长度就会变成3
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
// 开始以启动类扫描,这就是为什么启动类永远在所有包的最外层,如果要扫描其他模块或者启动类以外的包就要@ScanComponent这个注解
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
// 这里面就开始扫描doScan方法,只要是有@Component注解的都会把每个类的Definition放到scannedBeanDefinitions里面
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)) {
// 这里有事解析这个Bean,跟刚刚的parser.parse一样,只是一个是数组一个是单个Bean
// 并且他会递归调用doProcessConfigurationClass()方法,并且重新执行一次获取看看这个类有没有@ComponentScan,并且继续扫描直至结束
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}

// Process any @Import annotations
// 其实每一个parse方法都会走到这里,把每个类的注解都会去循环一次,直至没有注解位置,会把@Import注解的类全部加载出来,这就是自动装配的原理
// 这就是为什么我其他jar包的类可以给Spring管理@Import就是一个重点,把这个类导入到BeanFactory里面
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

/**
* 省略代码
*/
return null;
}

创建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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
java复制代码/**
* 创建bean实例,这里的方法过于复杂用文章非常难解释,笔者这里就把大致的思路说下
* 1.getBean的时候先去createBean如果有就返回没有的话doCreateBean
* 2.当doCreateBean的时候就会触发bean的生命周期的各个接口
* 3.其实笔者发现一个东西,ApplicationContextAware并不算是bean生命周期的一环把,而是输入上下文的一环
* 4.因为ApplicationContextAware其实是由添加了AnnotationConfigServletWebServerApplicationContext类所导致的
* 5.创建bean的我会有下面的uml图让大家更能理解Bean是如何创建的
*/
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}

// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

// Trigger initialization of all non-lazy singleton beans...
// 获取所有的BeanName
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}

// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}

关于ApplicationContext

实现ApplicationContextAware接口会调用setApplicationContext方法,而ApplicationContextAwareProcessor又是实现BeanPostProcessor,而ApplicationContextAwareProcessor又被Spring强制注册,所以说如果一个Bean实现ApplicationContextAware和BeanPostProcessor,在先初始化有关于BeanPostProcessor的Bean时候会创建这个Bean创建这个Bean的时候又会调用setApplicationContext方法调用完之后最后才会调用BeanPostProcessor实现的方法,其实听拗口的,所以最后还是希望自己能Debug一下

bean生命周期流程图

小结

当我重新重构这篇文章的时候,其实是因为我自己都读不懂之前的文章,希望这章大家可以看得懂。大家读不懂肯定是说明我的文采还不够好,也希望大家多多指出笔者的错误。

说到Spring其实在座的各位都是Spring工程师,老搬砖奴,但是大家肯定也因为忙没时间去研究整个Spring的流程。这里笔者帮大家都全部准备好了。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%