-
Notifications
You must be signed in to change notification settings - Fork 54
/
index.html
579 lines (451 loc) · 79.7 KB
/
index.html
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
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="UTF-8">
<title>Spring boot回调接口汇总 by chanjarster</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="stylesheets/normalize.css" media="screen">
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" type="text/css" href="stylesheets/stylesheet.css" media="screen">
<link rel="stylesheet" type="text/css" href="stylesheets/github-light.css" media="screen">
</head>
<body>
<section class="page-header">
<h1 class="project-name">Spring boot回调接口汇总</h1>
<h2 class="project-tagline"></h2>
<a href="https://github.com/chanjarster/spring-boot-all-callbacks" class="btn">View on GitHub</a>
<a href="https://github.com/chanjarster/spring-boot-all-callbacks/zipball/master" class="btn">Download .zip</a>
<a href="https://github.com/chanjarster/spring-boot-all-callbacks/tarball/master" class="btn">Download .tar.gz</a>
</section>
<section class="main-content">
<h1>
<a id="spring-boot启动过程及回调接口汇总" class="anchor" href="#spring-boot%E5%90%AF%E5%8A%A8%E8%BF%87%E7%A8%8B%E5%8F%8A%E5%9B%9E%E8%B0%83%E6%8E%A5%E5%8F%A3%E6%B1%87%E6%80%BB" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Spring Boot启动过程及回调接口汇总</h1>
<p>相关代码在: <a href="https://github.com/chanjarster/spring-boot-all-callbacks">https://github.com/chanjarster/spring-boot-all-callbacks</a></p>
<p>注:本文基于<a href="https://github.com/spring-projects/spring-boot/tree/v1.4.1.RELEASE">spring-boot 1.4.1.RELEASE</a>, <a href="https://github.com/spring-projects/spring-framework/tree/v4.3.3.RELEASE">spring 4.3.3.RELEASE</a>撰写。</p>
<h2>
<a id="启动顺序" class="anchor" href="#%E5%90%AF%E5%8A%A8%E9%A1%BA%E5%BA%8F" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>启动顺序</h2>
<p>Spring boot的启动代码一般是这样的:</p>
<div class="highlight highlight-source-java"><pre><span class="pl-k">@SpringBootApplication</span>
<span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-en">SampleApplication</span> {
<span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">void</span> <span class="pl-en">main</span>(<span class="pl-k">String</span>[] <span class="pl-v">args</span>) <span class="pl-k">throws</span> <span class="pl-smi">Exception</span> {
<span class="pl-smi">SpringApplication</span><span class="pl-k">.</span>run(<span class="pl-smi">SampleApplication</span><span class="pl-k">.</span>class, args);
}
}</pre></div>
<h3>
<a id="初始化springapplication" class="anchor" href="#%E5%88%9D%E5%A7%8B%E5%8C%96springapplication" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>初始化SpringApplication</h3>
<ol>
<li>
<code>SpringApplication#run(Object source, String... args)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L1174">#L1174</a>
</li>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L1186">SpringApplication#L1186</a> -> <code>SpringApplication(sources)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L236">#L236</a>
<ol>
<li>
<code>SpringApplication#initialize(Object[] sources)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L256">#L256</a> <a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/SpringApplication.html">javadoc</a>
<ol>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L257">SpringApplication#L257</a> 添加source(复数),<code>SpringApplication</code>使用source来构建Bean。一般来说在<code>run</code>的时候都会把<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/SpringBootApplication.html">@SpringBootApplication</a>标记的类(本例中是SampleApplication)放到<code>sources</code>参数里,然后由这个类出发找到Bean的定义。</li>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L261">SpringApplication#L261</a> 初始化<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContextInitializer.html">ApplicationContextInitializer</a>列表(见附录)</li>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L263">SpringApplication#L263</a> 初始化<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationListener.html">ApplicationListener</a>列表(见附录)</li>
</ol>
</li>
</ol>
</li>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L1186">SpringApplication#L1186</a> -> <code>SpringApplication#run(args)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L297">#L297</a>,进入运行阶段</li>
</ol>
<h3>
<a id="推送applicationstartedevent" class="anchor" href="#%E6%8E%A8%E9%80%81applicationstartedevent" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>推送ApplicationStartedEvent</h3>
<p><code>SpringApplication#run(args)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L297">#L297</a></p>
<ol>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L303">SpringApplication#L303</a> 初始化<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplicationRunListeners.java">SpringApplicationRunListeners</a> (<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/SpringApplicationRunListener.html">SpringApplicationRunListener</a>的集合)。它内部只包含<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/event/EventPublishingRunListener.html">EventPublishingRunListener</a>。</li>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L304">SpringApplication#L304</a> 推送<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/event/ApplicationStartedEvent.html">ApplicationStartedEvent</a>给所有的<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationListener.html">ApplicationListener</a>(见附录)。 下面是关心此事件的listener:
<ol>
<li><a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/liquibase/LiquibaseServiceLocatorApplicationListener.html">LiquibaseServiceLocatorApplicationListener</a></li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/logging/LoggingApplicationListener.html">LoggingApplicationListener</a>(见附录)</li>
</ol>
</li>
</ol>
<h3>
<a id="准备environment" class="anchor" href="#%E5%87%86%E5%A4%87environment" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>准备Environment</h3>
<p><code>SpringApplication#run(args)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L297">#L297</a>-><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L308">#L308</a>-><code>prepareEnvironment(...)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L331">#L331</a>准备<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/ConfigurableEnvironment.html">ConfigurableEnvironment</a>。</p>
<ol>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L335">SpringApplication#L335</a> 创建<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/StandardEnvironment.html">StandardEnvironment</a>(见附录)。</li>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L336">SpringApplication#L336</a> 配置<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/StandardEnvironment.html">StandardEnvironment</a>,将命令行和默认参数整吧整吧,添加到<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/MutablePropertySources.html">MutablePropertySources</a>。</li>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L337">SpringApplication#L337</a> 推送<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/event/ApplicationEnvironmentPreparedEvent.html">ApplicationEnvironmentPreparedEvent</a>给所有的<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationListener.html">ApplicationListener</a>(见附录)。下面是关心此事件的listener:
<ol>
<li><a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/BackgroundPreinitializer.html">BackgroundPreinitializer</a></li>
<li><a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/FileEncodingApplicationListener.html">FileEncodingApplicationListener</a></li>
<li><a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/config/AnsiOutputApplicationListener.html">AnsiOutputApplicationListener</a></li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/config/ConfigFileApplicationListener.html">ConfigFileApplicationListener</a>(见附录)</li>
<li><a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/config/DelegatingApplicationListener.html">DelegatingApplicationListener</a></li>
<li><a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/logging/ClasspathLoggingApplicationListener.html">ClasspathLoggingApplicationListener</a></li>
<li><a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/logging/LoggingApplicationListener.html">LoggingApplicationListener</a></li>
<li><a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/system/ApplicationPidFileWriter.html">ApplicationPidFileWriter</a></li>
</ol>
</li>
</ol>
<p>可以参考<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#boot-features-external-config">官方文档</a>了解<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/StandardEnvironment.html">StandardEnvironment</a>构建好之后,其<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/MutablePropertySources.html">MutablePropertySources</a>内部到底有些啥东东。</p>
<h3>
<a id="创建及准备applicationcontext" class="anchor" href="#%E5%88%9B%E5%BB%BA%E5%8F%8A%E5%87%86%E5%A4%87applicationcontext" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>创建及准备ApplicationContext</h3>
<p><code>SpringApplication#run(args)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L297">#L297</a></p>
<ol>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L311">SpringApplication#L311</a>-><code>SpringApplication#createApplicationContext()</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L583">#L583</a>创建<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContext.html">ApplicationContext</a>。可以看到实际上创建的是<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/AnnotationConfigApplicationContext.html">AnnotationConfigApplicationContext</a>或<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/embedded/AnnotationConfigEmbeddedWebApplicationContext.html">AnnotationConfigEmbeddedWebApplicationContext</a>。
<ol>
<li>在构造<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/AnnotationConfigApplicationContext.html">AnnotationConfigApplicationContext</a>的时候,间接注册了一个<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/support/BeanDefinitionRegistryPostProcessor.html">BeanDefinitionRegistryPostProcessor</a>的Bean:<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/ConfigurationClassPostProcessor.html">ConfigurationClassPostProcessor</a>。经由<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/AnnotatedBeanDefinitionReader.html">AnnotatedBeanDefinitionReader</a><a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/annotation/AnnotatedBeanDefinitionReader.java#L83">构造函数</a>-><a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java#L160">AnnotationConfigUtils.registerAnnotationConfigProcessors</a>。</li>
</ol>
</li>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L313">SpringApplication#L313</a>-><code>SpringApplication#prepareContext(...)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L344">#L344</a>准备<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContext.html">ApplicationContext</a>
<ol>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L347">SpringApplication#L347</a>-><code>context.setEnvironment(environment)</code>,把之前准备好的<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/Environment.html">Environment</a>塞给<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContext.html">ApplicationContext</a>
</li>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L348">SpringApplication#L348</a>-><code>postProcessApplicationContext(context)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L605">#L605</a>,给<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContext.html">ApplicationContext</a>设置了一些其他东西</li>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L349">SpringApplication#L349</a>-><code>applyInitializers(context)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L630">#L630</a>,调用之前准备好的<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContextInitializer.html">ApplicationContextInitializer</a>
</li>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L350">SpringApplication#L350</a>-><code>listeners.contextPrepared(context)</code>-><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/context/event/EventPublishingRunListener.java#L73">EventPublishingRunListener.contextPrepared</a>,但实际上啥都没做。</li>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L366">SpringApplication#L366</a>-><code>load</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L687">#L687</a>,负责将source(复数)里所定义的Bean加载到<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContext.html">ApplicationContext</a>里,在本例中就是SampleApplication,这些source是在<strong>初始化SpringApplication</strong>阶段获得的。</li>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L367">SpringApplication#L367</a>-><code>listeners.contextLoaded(context)</code>-><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/context/event/EventPublishingRunListener.java#L78">EventPublishingRunListener.contextLoaded</a>。
<ol>
<li>将<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/SpringApplication.html">SpringApplication</a>自己拥有的<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationListener.html">ApplicationListener</a>加入到<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContext.html">ApplicationContext</a>
</li>
<li>发送<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/event/ApplicationPreparedEvent.html">ApplicationPreparedEvent</a>。目前已知关心这个事件的有<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/config/ConfigFileApplicationListener.html">ConfigFileApplicationListener</a>、<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/logging/LoggingApplicationListener.html">LoggingApplicationListener</a>、<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/system/ApplicationPidFileWriter.html">ApplicationPidFileWriter</a>
</li>
</ol>
</li>
</ol>
</li>
</ol>
<p>要注意的是在这个阶段,<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContext.html">ApplicationContext</a>里只有SampleApplication,SampleApplication是Bean的加载工作的起点。</p>
<h3>
<a id="刷新applicationcontext" class="anchor" href="#%E5%88%B7%E6%96%B0applicationcontext" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>刷新ApplicationContext</h3>
<p>根据前面所讲,这里的<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContext.html">ApplicationContext</a>实际上是<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/support/GenericApplicationContext.html">GenericApplicationContext</a>
-><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/AnnotationConfigApplicationContext.html">AnnotationConfigApplicationContext</a>或者<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/embedded/AnnotationConfigEmbeddedWebApplicationContext.html">AnnotationConfigEmbeddedWebApplicationContext</a></p>
<p><code>SpringApplication#run(args)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L297">#L297</a>
-><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L315">#L315</a>-><code>SpringApplication#refreshContext(context)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L370">#L370</a>
-><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L371">#L371</a>-><code>SpringApplication#refresh(context)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L759">#L759</a>
-><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L761">#L761</a>-><code>AbstractApplicationContext#refresh</code><a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L507">AbstractApplicationContext#L507</a></p>
<ol>
<li>
<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L510">AbstractApplicationContext#L510</a>-><code>AbstractApplicationContext#prepareRefresh()</code><a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L575">#L575</a>,做了一些初始化工作,比如设置了当前Context的状态,初始化propertySource(其实啥都没干),检查required的property是否都已在Environment中(其实并没有required的property可供检查)等。</li>
<li>
<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L513">AbstractApplicationContext#L513</a>-><code>obtainFreshBeanFactory()</code><a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L611">#L611</a>,获得<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/BeanFactory.html">BeanFactory</a>,实际上这里获得的是<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/support/DefaultListableBeanFactory.html">DefaultListableBeanFactory</a>
</li>
<li>
<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L516">AbstractApplicationContext#L516</a>-><code>prepareBeanFactory(beanFactory)</code><a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L625">#L625</a>准备<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/BeanFactory.html">BeanFactory</a>
<ol>
<li>给beanFactory设置了ClassLoader</li>
<li>给beanFactory设置了<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/expression/StandardBeanExpressionResolver.html">SpEL解析器</a>
</li>
<li>给beanFactory设置了<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/PropertyEditorRegistrar.html">PropertyEditorRegistrar</a>
</li>
<li>给beanFactory添加了<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/ApplicationContextAwareProcessor.java">ApplicationContextAwareProcessor</a>(<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanPostProcessor.html">BeanPostProcessor</a>的实现类),需要注意的是它是第一个被添加到<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/BeanFactory.html">BeanFactory</a>的<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanPostProcessor.html">BeanPostProcessor</a>
</li>
<li>给beanFactory设置忽略解析以下类的依赖:<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ResourceLoaderAware.html">ResourceLoaderAware</a>、<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationEventPublisherAware.html">ApplicationEventPublisherAware</a>、<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/MessageSourceAware.html">MessageSourceAware</a>、<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContextAware.html">ApplicationContextAware</a>、<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/EnvironmentAware.html">EnvironmentAware</a>。原因是注入这些回调接口本身没有什么意义。</li>
<li>给beanFactory添加了以下类的依赖解析:<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/BeanFactory.html">BeanFactory</a>、<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/io/ResourceLoader.html">ResourceLoader</a>、<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationEventPublisher.html">ApplicationEventPublisher</a>、<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContext.html">ApplicationContext</a>
</li>
<li>给beanFactory添加<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/weaving/LoadTimeWeaverAwareProcessor.html">LoadTimeWeaverAwareProcessor</a>用来处理<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/weaving/LoadTimeWeaverAware.html">LoadTimeWeaverAware</a>的回调,在和AspectJ集成的时候会用到</li>
<li>把<code>getEnvironment()</code>作为Bean添加到beanFactory中,Bean Name: <code>environment</code>
</li>
<li>把<code>getEnvironment().getSystemProperties()</code>作为Bean添加到beanFactory中,Bean Name: <code>systemProperties</code>
</li>
<li>把<code>getEnvironment().getSystemEnvironment()</code>作为Bean添加到beanFactory中,Bean Name: <code>systemEnvironment</code>
</li>
</ol>
</li>
<li>
<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L520">AbstractApplicationContext#L520</a>-><code>postProcessBeanFactory(beanFactory)</code>,后置处理<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/BeanFactory.html">BeanFactory</a>,实际啥都没做</li>
<li>
<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L523">AbstractApplicationContext#L523</a>-><code>invokeBeanFactoryPostProcessors(beanFactory)</code>,利用<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanFactoryPostProcessor.html">BeanFactoryPostProcessor</a>,对beanFactory做后置处理。调用此方法时有四个<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanFactoryPostProcessor.html">BeanFactoryPostProcessor</a>:
<ol>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SharedMetadataReaderFactoryContextInitializer.java">SharedMetadataReaderFactoryContextInitializer</a>的内部类<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SharedMetadataReaderFactoryContextInitializer.java#L66">CachingMetadataReaderFactoryPostProcessor</a>,是在 <strong>创建及准备ApplicationContext 2.3</strong> 时添加的:<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SharedMetadataReaderFactoryContextInitializer.java#L57">#L57</a>
</li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/ConfigurationWarningsApplicationContextInitializer.html">ConfigurationWarningsApplicationContextInitializer</a>的内部类<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/context/ConfigurationWarningsApplicationContextInitializer.java#L75">ConfigurationWarningsPostProcessor</a>,是在 <strong>创建及准备ApplicationContext 2.3</strong> 时添加的:<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/context/ConfigurationWarningsApplicationContextInitializer.java#L60">#L60</a>
</li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/config/ConfigFileApplicationListener.html">ConfigFileApplicationListener</a>的内部类<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java#L285">PropertySourceOrderingPostProcessor</a>,是在 <strong>创建及准备ApplicationContext 2.6</strong> 时添加的:<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java#L158">#L158</a>-><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java#L199">#L199</a>-><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java#L244">#L244</a>
</li>
<li>
<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/ConfigurationClassPostProcessor.html">ConfigurationClassPostProcessor</a>,负责读取<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanDefinition.html">BeanDefinition</a>是在 <strong>创建及准备ApplicationContext 1.1</strong> 时添加的</li>
</ol>
</li>
<li>
<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L526">AbstractApplicationContext#L526</a>-><code>registerBeanPostProcessors(beanFactory)</code>,注册<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanPostProcessor.html">BeanPostProcessor</a>
</li>
<li>
<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L529">AbstractApplicationContext#L529</a>-><code>initMessageSource()</code><a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L704">#L704</a>,初始化<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/MessageSource.html">MessageSource</a>,不过其实此时的<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/MessageSource.html">MessageSource</a>是个Noop对象。</li>
<li>
<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L532">AbstractApplicationContext#L532</a>-><code>initApplicationEventMulticaster()</code><a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L739">#L739</a>,初始化<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/event/SimpleApplicationEventMulticaster.html">ApplicationEventMulticaster</a>。</li>
<li>
<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L535">AbstractApplicationContext#L535</a>-><code>onRefresh()</code><a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L793">#L793</a>,这个方法啥都没做</li>
<li>
<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L538">AbstractApplicationContext#L538</a>-><code>registerListeners()</code><a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L801">#L801</a>,把自己的<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationListener.html">ApplicationListener</a>注册到<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/event/SimpleApplicationEventMulticaster.html">ApplicationEventMulticaster</a>里,并且将之前因为没有<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/event/SimpleApplicationEventMulticaster.html">ApplicationEventMulticaster</a>而无法发出的<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationEvent.html">ApplicationEvent</a>发送出去。</li>
<li>
<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L541">AbstractApplicationContext#L541</a>-><code>finishBeanFactoryInitialization</code><a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L828">#L828</a>。注意<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L861">#L861</a>,在这一步的时候才会实例化所有non-lazy-init bean,这里说的实例化不只是new而已,注入、<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanPostProcessor.html">BeanPostProcessor</a>都会执行。</li>
<li>
<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L544">AbstractApplicationContext#L544</a>-><code>finishRefresh()</code><a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L869">#L869</a>。
<ol>
<li>在<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L877">#L877</a>发送了<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/event/ContextRefreshedEvent.html">ContextRefreshedEvent</a>
</li>
</ol>
</li>
</ol>
<h3>
<a id="调用-applicationrunner-和-commandlinerunner" class="anchor" href="#%E8%B0%83%E7%94%A8-applicationrunner-%E5%92%8C-commandlinerunner" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>调用 ApplicationRunner 和 CommandLineRunner</h3>
<p><code>SpringApplication#run(args)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L297">#L297</a>
-><code>afterRefresh(context, applicationArguments)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L316">#L316</a>
-><code>callRunners(context, args)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L771">#L771</a>
-><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L774">#L774</a> 先后调用了当前<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContext.html">ApplicationContext</a>中的<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/ApplicationRunner.html">ApplicationRunner</a>和<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/CommandLineRunner.html">CommandLineRunner</a>。关于它们的相关文档可以看<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#boot-features-command-line-runner">这里</a>。</p>
<p>需要注意的是,此时的<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContext.html">ApplicationContext</a>已经刷新完毕了,该有的Bean都已经有了。</p>
<h3>
<a id="推送applicationreadyevent-or-applicationfailedevent" class="anchor" href="#%E6%8E%A8%E9%80%81applicationreadyevent-or-applicationfailedevent" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>推送ApplicationReadyEvent or ApplicationFailedEvent</h3>
<p><code>SpringApplication#run(args)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L297">#L297</a>-><code>listeners.finished(context, null)</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L317">#L317</a>
间接地调用了<code>EventPublishingRunListener#getFinishedEvent</code><a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/context/event/EventPublishingRunListener.java#L96">EventPublishingRunListener#L96</a>,发送了<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/event/ApplicationReadyEvent.html">ApplicationReadyEvent</a>或<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/event/ApplicationFailedEvent.html">ApplicationFailedEvent</a></p>
<h2>
<a id="回调接口" class="anchor" href="#%E5%9B%9E%E8%B0%83%E6%8E%A5%E5%8F%A3" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>回调接口</h2>
<h3>
<a id="applicationcontextinitializer" class="anchor" href="#applicationcontextinitializer" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>ApplicationContextInitializer</h3>
<p><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContextInitializer.html">javadoc</a> <a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#howto-customize-the-environment-or-application-context">相关文档</a></p>
<p>加载方式:读取<code>classpath*:META-INF/spring.factories</code>中key等于<code>org.springframework.context.ApplicationContextInitializer</code>的property列出的类</p>
<p>排序方式:<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/annotation/AnnotationAwareOrderComparator.html">AnnotationAwareOrderComparator</a></p>
<p>已知清单1:spring-boot-1.4.1.RELEASE.jar!/META-INF/spring.factories</p>
<ol>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/ConfigurationWarningsApplicationContextInitializer.html">ConfigurationWarningsApplicationContextInitializer</a>(优先级:0)</li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/ContextIdApplicationContextInitializer.html">ContextIdApplicationContextInitializer</a>(优先级:Ordered.LOWEST_PRECEDENCE - 10)</li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/config/DelegatingApplicationContextInitializer.html">DelegatingApplicationContextInitializer</a>(优先级:无=Ordered.LOWEST_PRECEDENCE)</li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/web/ServerPortInfoApplicationContextInitializer.html">ServerPortInfoApplicationContextInitializer</a>(优先级:无=Ordered.LOWEST_PRECEDENCE)</li>
</ol>
<p>已知清单2:spring-boot-autoconfigure-1.4.1.RELEASE.jar!/META-INF/spring.factories</p>
<ol>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SharedMetadataReaderFactoryContextInitializer.java">SharedMetadataReaderFactoryContextInitializer</a>(优先级:无=Ordered.LOWEST_PRECEDENCE)</li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/logging/AutoConfigurationReportLoggingInitializer.html">AutoConfigurationReportLoggingInitializer</a>(优先级:无=Ordered.LOWEST_PRECEDENCE)</li>
</ol>
<h3>
<a id="applicationlistener" class="anchor" href="#applicationlistener" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>ApplicationListener</h3>
<p><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationListener.html">javadoc</a> <a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#howto-customize-the-environment-or-application-context">相关文档</a></p>
<p>加载方式:读取<code>classpath*:META-INF/spring.factories</code>中key等于<code>org.springframework.context.ApplicationListener</code>的property列出的类</p>
<p>排序方式:<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/annotation/AnnotationAwareOrderComparator.html">AnnotationAwareOrderComparator</a></p>
<p>已知清单1:spring-boot-1.4.1.RELEASE.jar!/META-INF/spring.factories中定义的</p>
<ol>
<li>
<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot/src/main/java/org/springframework/boot/ClearCachesApplicationListener.java">ClearCachesApplicationListener</a>(优先级:无=Ordered.LOWEST_PRECEDENCE)</li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/builder/ParentContextCloserApplicationListener.html">ParentContextCloserApplicationListener</a>(优先级:Ordered.LOWEST_PRECEDENCE - 10)</li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/FileEncodingApplicationListener.html">FileEncodingApplicationListener</a>(优先级:Ordered.LOWEST_PRECEDENCE)</li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/config/AnsiOutputApplicationListener.html">AnsiOutputApplicationListener</a>(优先级:ConfigFileApplicationListener.DEFAULT_ORDER + 1)</li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/config/ConfigFileApplicationListener.html">ConfigFileApplicationListener</a>(优先级:Ordered.HIGHEST_PRECEDENCE + 10)</li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/config/DelegatingApplicationListener.html">DelegatingApplicationListener</a>(优先级:0)</li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/liquibase/LiquibaseServiceLocatorApplicationListener.html">LiquibaseServiceLocatorApplicationListener</a>(优先级:无=Ordered.LOWEST_PRECEDENCE)</li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/logging/ClasspathLoggingApplicationListener.html">ClasspathLoggingApplicationListener</a>(优先级:LoggingApplicationListener的优先级 + 1)</li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/logging/LoggingApplicationListener.html">LoggingApplicationListener</a>(优先级:Ordered.HIGHEST_PRECEDENCE + 20)</li>
</ol>
<p>已知清单2:spring-boot-autoconfigure-1.4.1.RELEASE.jar!/META-INF/spring.factories中定义的</p>
<ol>
<li><a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/BackgroundPreinitializer.html">BackgroundPreinitializer</a></li>
</ol>
<h3>
<a id="springapplicationrunlistener" class="anchor" href="#springapplicationrunlistener" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>SpringApplicationRunListener</h3>
<p><a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/SpringApplicationRunListener.html">javadoc</a> </p>
<p>加载方式:读取<code>classpath*:META-INF/spring.factories</code>中key等于<code>org.springframework.boot.SpringApplicationRunListener</code>的property列出的类</p>
<p>排序方式:<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/annotation/AnnotationAwareOrderComparator.html">AnnotationAwareOrderComparator</a></p>
<p>已知清单:spring-boot-1.4.1.RELEASE.jar!/META-INF/spring.factories定义的</p>
<ol>
<li>org.springframework.boot.context.event.EventPublishingRunListener(优先级:0)</li>
</ol>
<h3>
<a id="environmentpostprocessor" class="anchor" href="#environmentpostprocessor" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>EnvironmentPostProcessor</h3>
<p><a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/env/EnvironmentPostProcessor.html">EnvironmentPostProcessor</a>可以用来自定义<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/StandardEnvironment.html">StandardEnvironment</a>(<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#howto-customize-the-environment-or-application-context">相关文档</a>)。</p>
<p>加载方式:读取<code>classpath*:META-INF/spring.factories</code>中key等于<code>org.springframework.boot.env.EnvironmentPostProcessor</code>的property列出的类</p>
<p>排序方式:<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/annotation/AnnotationAwareOrderComparator.html">AnnotationAwareOrderComparator</a></p>
<p>已知清单:spring-boot-1.4.1.RELEASE.jar!/META-INF/spring.factories定义的</p>
<ol>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/cloud/CloudFoundryVcapEnvironmentPostProcessor.html">CloudFoundryVcapEnvironmentPostProcessor</a>(优先级:ConfigFileApplicationListener.DEFAULT_ORDER - 1)</li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/env/SpringApplicationJsonEnvironmentPostProcessor.html">SpringApplicationJsonEnvironmentPostProcessor</a>(优先级:Ordered.HIGHEST_PRECEDENCE + 5)</li>
</ol>
<h3>
<a id="beanpostprocessor" class="anchor" href="#beanpostprocessor" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>BeanPostProcessor</h3>
<p><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanPostProcessor.html">javadoc</a> <a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/spring-framework-reference/htmlsingle/#beans-factory-extension-bpp">相关文档</a></p>
<p>用来对Bean<strong>实例</strong>进行修改的勾子,根据Javadoc ApplicationContext会自动侦测到BeanPostProcessor Bean,然后将它们应用到后续创建的所有Bean上。</p>
<h3>
<a id="beanfactorypostprocessor和beandefinitionregistrypostprocessor" class="anchor" href="#beanfactorypostprocessor%E5%92%8Cbeandefinitionregistrypostprocessor" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor</h3>
<p><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/spring-framework-reference/htmlsingle/#beans-factory-extension-factory-postprocessors">相关文档</a></p>
<p><a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/PostProcessorRegistrationDelegate.java#L57">PostProcessorRegistrationDelegate</a>负责调用<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/support/BeanDefinitionRegistryPostProcessor.html">BeanDefinitionRegistryPostProcessor</a>和<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanFactoryPostProcessor.html">BeanFactoryPostProcessor</a>。
<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/support/BeanDefinitionRegistryPostProcessor.html">BeanDefinitionRegistryPostProcessor</a>在<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanFactoryPostProcessor.html">BeanFactoryPostProcessor</a>之前被调用。</p>
<h3>
<a id="aware" class="anchor" href="#aware" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>*Aware</h3>
<p>*Aware是一类可以用来获得Spring对象的interface,这些interface都继承了<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/Aware.html">Aware</a>,已知的有:</p>
<ul>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationEventPublisherAware.html">ApplicationEventPublisherAware</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/jmx/export/notification/NotificationPublisherAware.html">NotificationPublisherAware</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/MessageSourceAware.html">MessageSourceAware</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/EnvironmentAware.html">EnvironmentAware</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/BeanFactoryAware.html">BeanFactoryAware</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/EmbeddedValueResolverAware.html">EmbeddedValueResolverAware</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ResourceLoaderAware.html">ResourceLoaderAware</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/ImportAware.html">ImportAware</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/weaving/LoadTimeWeaverAware.html">LoadTimeWeaverAware</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/BeanNameAware.html">BeanNameAware</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/BeanClassLoaderAware.html">BeanClassLoaderAware</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContextAware.html">ApplicationContextAware</a></li>
</ul>
<h2>
<a id="configuration-和-auto-configuration" class="anchor" href="#configuration-%E5%92%8C-auto-configuration" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a><a href="https://github.com/Configuration" class="user-mention">@Configuration</a> 和 Auto-configuration</h2>
<p><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>替代xml来定义<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanDefinition.html">BeanDefinition</a>的一种手段。<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#using-boot-auto-configuration">Auto-configuration</a>也是定义<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanDefinition.html">BeanDefinition</a>的一种手段。</p>
<p>这两者的相同之处有:</p>
<ol>
<li>都是使用<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>注解的类,这些类里都可以定义<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Bean.html">@Bean</a>、<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Import.html">@Import</a>、<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/ImportResource.html">@ImportResource</a>。</li>
<li>都可以使用<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#boot-features-condition-annotations">@Condition*</a>来根据情况选择是否加载</li>
</ol>
<p>而不同之处有:</p>
<ol>
<li>加载方式不同:
<ul>
<li>普通<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>则是通过扫描package path加载的 </li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#using-boot-auto-configuration">Auto-configuration</a>的是通过读取<code>classpath*:META-INF/spring.factories</code>中key等于<code>org.springframework.boot.autoconfigure.EnableAutoConfiguration</code>的property列出的<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>加载的</li>
</ul>
</li>
<li>加载顺序不同:普通<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>的加载永远在<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#using-boot-auto-configuration">Auto-configuration</a>之前</li>
<li>内部加载顺序可控上的不同:
<ul>
<li>普通<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>则无法控制加载顺序</li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#using-boot-auto-configuration">Auto-configuration</a>可以使用<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/AutoConfigureOrder.html">@AutoConfigureOrder</a>、<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/AutoConfigureBefore.html">@AutoConfigureBefore</a>、<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/AutoConfigureAfter.html">@AutoConfigureAfter</a>
</li>
</ul>
</li>
</ol>
<p>参考<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/EnableAutoConfiguration.html">EnableAutoConfiguration</a>和附录<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelector.html">EnableAutoConfigurationImportSelector</a>了解Spring boot内部处理机制</p>
<h3>
<a id="annotatedbeandefinitionreader" class="anchor" href="#annotatedbeandefinitionreader" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>AnnotatedBeanDefinitionReader</h3>
<p>这个类用来读取<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>和<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/stereotype/Component.html">@Component</a>,并将<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanDefinition.html">BeanDefinition</a>注册到<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContext.html">ApplicationContext</a>里。</p>
<h3>
<a id="configurationclasspostprocessor" class="anchor" href="#configurationclasspostprocessor" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>ConfigurationClassPostProcessor</h3>
<p><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/ConfigurationClassPostProcessor.html">ConfigurationClassPostProcessor</a>是一个<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/support/BeanDefinitionRegistryPostProcessor.html">BeanDefinitionRegistryPostProcessor</a>,负责处理<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>。</p>
<p>需要注意一个烟雾弹:看<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java#L296">#L296</a>-><a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java#L209">ConfigurationClassUtils#L209</a>。而order的值则是在<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java#L122">ConfigurationClassUtils#L122</a>从注解中提取的。
这段代码似乎告诉我们它会对<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>进行排序,然后按次序加载。
实际上不是的,<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>是一个递归加载的过程。在本例中,是先从SampleApplication开始加载的,而事实上在这个时候,也就只有SampleApplication它自己可以提供排序。
而之后则直接使用了<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java">ConfigurationClassParser</a>,它里面并没有排序的逻辑。</p>
<p>关于排序的方式简单来说是这样的:<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>的排序根据且只根据<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/annotation/Order.html">@Order</a>排序,如果没有<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/annotation/Order.html">@Order</a>则优先级最低。</p>
<h3>
<a id="configurationclassparser" class="anchor" href="#configurationclassparser" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>ConfigurationClassParser</h3>
<p>前面讲了<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/ConfigurationClassPostProcessor.html">ConfigurationClassPostProcessor</a>使用<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java">ConfigurationClassParser</a>,实际上加载<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>的工作是在这里做的。</p>
<p>下面讲以下加载的顺序:</p>
<ol>
<li>以SampleApplication为起点开始扫描</li>
<li>扫描得到所有的<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>和<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/stereotype/Component.html">@Component</a>,从中读取<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanDefinition.html">BeanDefinition</a>并导入:
<ol>
<li>如果<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>注解了<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Import.html">@Import</a>
<ol>
<li>如果使用的是<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/ImportSelector.html">ImportSelector</a>,则递归导入</li>
<li>如果使用的是<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/ImportBeanDefinitionRegistrar.html">ImportBeanDefinitionRegistrar</a>,则递归导入</li>
<li>如果使用的是<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/DeferredImportSelector.html">DeferredImportSelector</a>,则仅收集不导入</li>
</ol>
</li>
<li>如果<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>注解了<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/ImportResource.html">@ImportResource</a>,则递归导入</li>
</ol>
</li>
<li>迭代之前收集的<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/DeferredImportSelector.html">DeferredImportSelector</a>,递归导入</li>
</ol>
<p>那<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#using-boot-auto-configuration">Auto-configuration</a>在哪里呢?
实际上是在第3步里,<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/SpringBootApplication.html">@SpringBootApplication</a>存在注解<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/EnableAutoConfiguration.html">@EnableAutoConfiguration</a>,它使用了<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelector.html">EnableAutoConfigurationImportSelector</a>,
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelector.html">EnableAutoConfigurationImportSelector</a>是一个<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/DeferredImportSelector.html">DeferredImportSelector</a>,所以也就是说,<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#using-boot-auto-configuration">Auto-configuration</a>是在普通<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>之后再加载的。</p>
<p>不过需要注意以下陷阱:</p>
<ol>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#using-boot-auto-configuration">Auto-configuration</a>不能出现在最初的扫描路径里,这样就会被提前加载到,然后被当作普通的<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>处理,这样<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/AutoConfigureBefore.html">@AutoConfigureBefore</a>和<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/AutoConfigureAfter.html">@AutoConfigureAfter</a>就没用了。
参看例子代码里的InsideAutoConfiguration和InsideAutoConfiguration2。</li>
<li>
<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#using-boot-auto-configuration">Auto-configuration</a>里再使用<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/DeferredImportSelector.html">DeferredImportSelector</a>和使用<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/ImportSelector.html">ImportSelector</a>效果是一样的,不会再被延后处理。参见例子代码里的UselessDeferredImportSelectorAutoConfiguration。</li>
</ol>
<h3>
<a id="enableautoconfigurationimportselector" class="anchor" href="#enableautoconfigurationimportselector" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>EnableAutoConfigurationImportSelector</h3>
<p><a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelector.html">EnableAutoConfigurationImportSelector</a>负责导入<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#using-boot-auto-configuration">Auto-configuration</a>。</p>
<p>它利用<a href="https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationSorter.java">AutoConfigurationSorter</a>对<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#using-boot-auto-configuration">Auto-configuration</a>进行排序。逻辑算法是:</p>
<ol>
<li>先根据类名排序</li>
<li>再根据<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/AutoConfigureOrder.html">@AutoConfigureOrder</a>排序,如果没有<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/AutoConfigureOrder.html">@AutoConfigureOrder</a>则优先级最低</li>
<li>再根据<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/AutoConfigureBefore.html">@AutoConfigureBefore</a>,<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/autoconfigure/AutoConfigureAfter.html">@AutoConfigureAfter</a>排序</li>
</ol>
<h2>
<a id="内置类说明" class="anchor" href="#%E5%86%85%E7%BD%AE%E7%B1%BB%E8%AF%B4%E6%98%8E" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>内置类说明</h2>
<h3>
<a id="loggingapplicationlistener" class="anchor" href="#loggingapplicationlistener" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>LoggingApplicationListener</h3>
<p><a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/logging/LoggingApplicationListener.html">LoggingApplicationListener</a>用来配置日志系统的,比如logback、log4j。Spring boot对于日志有<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#boot-features-logging">详细解释</a>,如果你想<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#boot-features-custom-log-configuration">自定义日志配置</a>,那么也请参考本文中对于<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/logging/LoggingApplicationListener.html">LoggingApplicationListener</a>的被调用时机的说明以获得更深入的了解。</p>
<h3>
<a id="standardenvironment" class="anchor" href="#standardenvironment" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>StandardEnvironment</h3>
<p><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/StandardEnvironment.html">StandardEnvironment</a>有一个<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/MutablePropertySources.html">MutablePropertySources</a>,它里面有多个<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/PropertySource.html">PropertySource</a>,<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/PropertySource.html">PropertySource</a>负责提供property(即property的提供源),目前已知的<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/PropertySource.html">PropertySource</a>实现有:<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/MapPropertySource.html">MapPropertySource</a>、<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/SystemEnvironmentPropertySource.html">SystemEnvironmentPropertySource</a>、<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/CommandLinePropertySource.html">CommandLinePropertySource</a>等。当<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/StandardEnvironment.html">StandardEnvironment</a>查找property值的时候,是从<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/MutablePropertySources.html">MutablePropertySources</a>里依次查找的,而且一旦查找到就不再查找,也就是说如果要覆盖property的值,那么就得提供顺序在前的<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/PropertySource.html">PropertySource</a>。</p>
<h3>
<a id="configfileapplicationlistener" class="anchor" href="#configfileapplicationlistener" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>ConfigFileApplicationListener</h3>
<p><a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/config/ConfigFileApplicationListener.html">ConfigFileApplicationListener</a>用来将<code>application.properties</code>加载到<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/StandardEnvironment.html">StandardEnvironment</a>中。</p>
<p><a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/context/config/ConfigFileApplicationListener.html">ConfigFileApplicationListener</a>内部使用了<a href="http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/api/org/springframework/boot/env/EnvironmentPostProcessor.html">EnvironmentPostProcessor</a>(见附录)自定义<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/core/env/StandardEnvironment.html">StandardEnvironment</a></p>
<h3>
<a id="applicationcontextawareprocessor" class="anchor" href="#applicationcontextawareprocessor" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>ApplicationContextAwareProcessor</h3>
<p><a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/support/ApplicationContextAwareProcessor.java">ApplicationContextAwareProcessor</a>实现了<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanPostProcessor.html">BeanPostProcessor</a>接口,根据javadoc这个类用来调用以下接口的回调方法:</p>
<ol>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/EnvironmentAware.html">EnvironmentAware</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/EmbeddedValueResolverAware.html">EmbeddedValueResolverAware</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ResourceLoaderAware.html">ResourceLoaderAware</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationEventPublisherAware.html">ApplicationEventPublisherAware</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/MessageSourceAware.html">MessageSourceAware</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/ApplicationContextAware.html">ApplicationContextAware</a></li>
</ol>
<h3>
<a id="annotationconfigapplicationcontext" class="anchor" href="#annotationconfigapplicationcontext" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>AnnotationConfigApplicationContext</h3>
<p>根据<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/AnnotationConfigApplicationContext.html">javadoc</a>,这个类用来将<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>和<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/stereotype/Component.html">@Component</a>作为输入来注册BeanDefinition。</p>
<p>特别需要注意的是,在<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/AnnotationConfigApplicationContext.html">javadoc</a>中讲到其支持<a href="https://github.com/Bean" class="user-mention">@Bean</a>的覆盖:</p>
<blockquote>
<p>In case of multiple <a href="https://github.com/Configuration" class="user-mention">@Configuration</a> classes, <a href="https://github.com/Bean" class="user-mention">@Bean</a> methods defined in later classes will override those defined in earlier classes. This can be leveraged to deliberately override certain bean definitions via an extra <a href="https://github.com/Configuration" class="user-mention">@Configuration</a> class.</p>
</blockquote>
<p>它使用<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/AnnotatedBeanDefinitionReader.html">AnnotatedBeanDefinitionReader</a>来读取<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html">@Configuration</a>和<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/stereotype/Component.html">@Component</a>。</p>
<h3>
<a id="annotatedbeandefinitionreader-1" class="anchor" href="#annotatedbeandefinitionreader-1" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>AnnotatedBeanDefinitionReader</h3>
<p><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/AnnotatedBeanDefinitionReader.html">AnnotatedBeanDefinitionReader</a>在其构造函数内部间接(<a href="https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java#L145">AnnotationConfigUtils#L145</a>)的给<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/BeanFactory.html">BeanFactory</a>注册了几个与<a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanDefinition.html">BeanDefinition</a>相关注解的处理器。</p>
<ol>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/ConfigurationClassPostProcessor.html">ConfigurationClassPostProcessor</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html">AutowiredAnnotationBeanPostProcessor</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/beans/factory/annotation/RequiredAnnotationBeanPostProcessor.html">RequiredAnnotationBeanPostProcessor</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.html">CommonAnnotationBeanPostProcessor</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/context/event/EventListenerMethodProcessor.html">EventListenerMethodProcessor</a></li>
<li><a href="http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.html">PersistenceAnnotationBeanPostProcessor</a></li>
</ol>
<footer class="site-footer">
<span class="site-footer-owner"><a href="https://github.com/chanjarster/spring-boot-all-callbacks">Spring boot回调接口汇总</a> is maintained by <a href="https://github.com/chanjarster">chanjarster</a>.</span>
<span class="site-footer-credits">This page was generated by <a href="https://pages.github.com">GitHub Pages</a> using the <a href="https://github.com/jasonlong/cayman-theme">Cayman theme</a> by <a href="https://twitter.com/jasonlong">Jason Long</a>.</span>
</footer>
</section>
</body>
</html>