@@ -80,7 +80,7 @@ $ java -jar myproject-0.0.1-SNAPSHOT.jar --debug
80
80
| ` ${application.version} ` | 您的应用版本号,声明在 ` MANIFEST.MF ` 中。例如,` Implementation-Version: 1.0 ` 将被打印为 ` 1.0 ` 。 |
81
81
| ` ${application.formatted-version} ` | 您的应用版本号,声明在 ` MANIFEST.MF ` 中,格式化之后打印(用括号括起来,以 ` v ` 为前缀),例如 (` v1.0 ` )。 |
82
82
| ` ${spring-boot.version} ` | 您使用的 Spring Boot 版本。例如 ` 2.1.1.RELEASE. ` 。 |
83
- | ` ${spring-boot.formatted-version} ` | 你使用的 Spring Boot 版本格式化之后显示(用括号括起来,以 ` v ` 为前缀)。例如 (` v2.1.1.RELEASE ` )。 |
83
+ | ` ${spring-boot.formatted-version} ` | 您使用的 Spring Boot 版本格式化之后显示(用括号括起来,以 ` v ` 为前缀)。例如 (` v2.1.1.RELEASE ` )。 |
84
84
| ` ${Ansi.NAME} ` (或 ` ${AnsiColor.NAME} ` 、<br />` ${AnsiBackground.NAME} ` 、<br />` ${AnsiStyle.NAME} ` )| 其中 ` NAME ` 是 ANSI 转义码的名称。有关详细信息,请参阅 [ AnsiPropertySource] ( https://github.com/spring-projects/spring-boot/tree/v2.1.1.RELEASE/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiPropertySource.java ) 。 |
85
85
| ` ${application.title} ` | 您的应用标题,声明在 ` MANIFEST.MF ` 中,例如 ` Implementation-Title: MyApp ` 打印为 ` MyApp ` 。 |
86
86
@@ -103,4 +103,247 @@ spring:
103
103
banner-mode : " off"
104
104
` ` `
105
105
106
+ <a id="boot-features-customizing-spring-application"></a>
107
+
108
+ ### 23.3、自定义 SpringApplication
109
+
110
+ 如果 ` SpringApplication` 的默认设置不符合您的想法,您可以创建本地实例进行定制化。例如,要关闭 banner,您可以这样:
111
+
112
+ ` ` ` java
113
+ public static void main(String[] args) {
114
+ SpringApplication app = new SpringApplication(MySpringConfiguration.class);
115
+ app.setBannerMode(Banner.Mode.OFF);
116
+ app.run(args);
117
+ }
118
+ ` ` `
119
+
120
+ **注意**
121
+
122
+ > 传入 `SpringApplication` 的构造参数是 spring bean 的配置源。大多情况下是引用 `@Configuration` 类,但您也可以引用 XML 配置或者被扫描的包。
123
+
124
+ 也可以使用 `application.properties` 文件配置 `SpringApplication`。有关详细信息,请参见[第 24 章:外部化配置](#boot-features-external-config)。
125
+
126
+ 关于配置选项的完整列表,请参阅 [SpringApplication Javadoc](https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/api/org/springframework/boot/SpringApplication.html)。
127
+
128
+ <a id="boot-features-customizing-spring-application"></a>
129
+
130
+ # ## 23.4、Fluent Builder API
131
+
132
+ 如果您需要构建一个有层级关系的 `ApplicationContext`(具有父/子关系的多上下文),或者偏向使用 **fluent**(流畅)构建器 API,可以使用 `SpringApplicationBuilder`。
133
+
134
+ ` SpringApplicationBuilder` 允许您链式调用多个方法,包括能创建出具有层次结构的 `parent` 和 `child` 方法。
135
+
136
+ 例如:
137
+
138
+ ` ` ` java
139
+ new SpringApplicationBuilder()
140
+ .sources(Parent.class)
141
+ .child(Application.class)
142
+ .bannerMode(Banner.Mode.OFF)
143
+ .run(args);
144
+ ` ` `
145
+
146
+ **注意**
147
+
148
+ > 创建层级的 `ApplicationContext` 时有部分限制,比如 Web 组件**必须**包含在子上下文中,并且相同的 `Environment` 将作用于父子上下文。有关详细信息,请参阅 [SpringApplicationBuilder Javadoc](https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/api/org/springframework/boot/builder/SpringApplicationBuilder.html)。
149
+
150
+ <a id="boot-features-application-events-and-listeners"></a>
151
+
152
+ # ## 23.5、应用程序事件与监听器
153
+
154
+ 除了常见的 Spring Framework 事件,比如 [`ContextRefreshedEvent`](https://docs.spring.io/spring/docs/5.1.3.RELEASE/javadoc-api/org/springframework/context/event/ContextRefreshedEvent.html),`SpringApplication` 还会发送其他应用程序事件。
155
+
156
+ **注意**
157
+
158
+ > 在 `ApplicationContext` 创建之前,实际上触发了一些事件,因此您不能像 `@Bean` 一样注册监听器。您可以通过 `SpringApplication.addListeners(...)` 或者 `SpringApplicationBuilder.listeners(...)` 方法注册它们。如果您希望无论应用使用何种创建方式都能自动注册这些监听器,您都可以将 `META-INF/spring.factories` 文件添加到项目中,并使用 `org.springframework.context.ApplicationListener ` 属性键指向您的监听器。比如:`org.springframework.context.ApplicationListener=com.example.project.MyListener`
159
+
160
+ 当您运行应用时,应用程序事件将按照以下顺序发送:
161
+
162
+ 1. 在开始应用开始运行但还没有进行任何处理时(除了注册监听器和初始化器[initializer]),将发送 `ApplicationStartingEvent`。
163
+ 2. 当 `Environment` 被上下文使用,但是在上下文创建之前,将发送 `ApplicationEnvironmentPreparedEvent`。
164
+ 3. 在开始刷新之前,bean 定义被加载之后发送 `ApplicationPreparedEvent`。
165
+ 4. 在上下文刷新之后且所有的应用和命令行运行器(command-line runner)被调用之前发送 `ApplicationStartedEvent`。
166
+ 5. 在应用程序和命令行运行器(command-line runner)被调用之后,将发出 `ApplicationReadyEvent`,该事件用于通知应用已经准备处理请求。
167
+ 6. 如果启动时发生异常,将发送 `ApplicationFailedEvent`。
168
+
169
+ **提示**
170
+
171
+ > 您可能不会经常使用应用程序事件,但了解他们的存在还是很有必要的。在框架内部,Spring Boot 使用这些事件来处理各种任务。
172
+
173
+ 应用程序事件发送使用了 Spring Framework 的事件发布机制。该部分机制确保在子上下文中发布给监听器的事件也会发布给所有祖先上下文中的监听器。因此,如果您的应用程序使用有层级结构的 SpringApplication 实例,则监听器可能会收到同种类型应用程序事件的多个实例。
174
+
175
+ 为了让监听器能够区分其上下文事件和后代上下文事件,您应该注入其应用程序上下文,然后将注入的上下文与事件的上下文进行比较。可以通过实现 `ApplicationContextAware` 来注入上下文,如果监听器是 bean,则使用 `@Autowired` 注入上下文。
176
+
177
+ <a id="boot-features-web-environment"></a>
178
+
179
+ # ## 23.6、Web 环境
180
+
181
+ ` SpringApplication` 试图为您创建正确类型的 `ApplicationContext`。确定 `WebApplicationType` 的算法非常简单:
182
+
183
+ - 如果存在 Spring MVC,则使用 `AnnotationConfigServletWebServerApplicationContext`
184
+ - 如果 Spring MVC 不存在且存在 Spring WebFlux,则使用 `AnnotationConfigReactiveWebServerApplicationContext`
185
+ - 否则,使用 `AnnotationConfigApplicationContext`
186
+
187
+ 这意味着如果您在同一个应用程序中使用了 Spring MVC 和 Spring WebFlux 中的新 `WebClient`,默认情况下将使用 Spring MVC。您可以通过调用 `setWebApplicationType(WebApplicationType)` 修改默认行为。
188
+
189
+ 也可以调用 `setApplicationContextClass(...)` 来完全控制 `ApplicationContext` 类型。
190
+
191
+ **提示**
192
+
193
+ > 在 JUnit 测试中使用 `SpringApplication` 时,通常需要调用 `setWebApplicationType(WebApplicationType.NONE)`。
194
+
195
+ <a id="boot-features-application-arguments"></a>
196
+
197
+ # ## 23.7、访问应用程序参数
198
+
199
+ 如果您需要访问从 `SpringApplication.run(...) ` 传入的应用程序参数,可以注入一个 `org.springframework.boot.ApplicationArguments` bean。`ApplicationArguments` 接口提供了访问原始 `String[]` 参数以及解析后的 `option` 和 `non-option` 参数的方法:
200
+
201
+ ` ` ` java
202
+ import org.springframework.boot.*;
203
+ import org.springframework.beans.factory.annotation.*;
204
+ import org.springframework.stereotype.*;
205
+
206
+ @Component
207
+ public class MyBean {
208
+
209
+ @Autowired
210
+ public MyBean(ApplicationArguments args) {
211
+ boolean debug = args.containsOption("debug");
212
+ List<String> files = args.getNonOptionArgs();
213
+ // if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
214
+ }
215
+
216
+ }
217
+ ` ` `
218
+
219
+ **提示**
220
+
221
+ > Spring Boot 还向 Spring `Environment` 注册了一个 `CommandLinePropertySource`。这允许您可以使用 `@Value` 注解注入单个应用参数。
222
+
223
+ <a id="boot-features-command-line-runner"></a>
224
+
225
+ # ## 23.8、使用 ApplicationRunner 或 ApplicationRunner
226
+
227
+ 如果您需要在 SpringApplication 启动时运行一些代码,可以实现 `ApplicationRunner` 或者 `CommandLineRunner` 接口。这两个接口的工作方式是一样的,都提供了一个单独的 `run` 方法,它将在 `SpringApplication.run(...)` 完成之前调用。
228
+
229
+ ` CommandLineRunner` 接口提供了访问应用程序字符串数组形式参数的方法,而 `ApplicationRunner` 则使用了上述的 `ApplicationArguments` 接口。以下示例展示 `CommandLineRunner` 和 `run` 方法的使用:
230
+
231
+ ` ` ` java
232
+ import org.springframework.boot.*;
233
+ import org.springframework.stereotype.*;
234
+
235
+ @Component
236
+ public class MyBean implements CommandLineRunner {
237
+
238
+ public void run(String... args) {
239
+ // Do something...
240
+ }
241
+
242
+ }
243
+ ` ` `
244
+
245
+ 如果您定义了多个 `CommandLineRunner` 或者 `ApplicationRunner` bean,则必须指定调用顺序,您可以实现 `org.springframework.core.Ordered` 接口,也可以使用 `org.springframework.core.annotation.Order` 注解解决顺序问题。
246
+
247
+ <a id="boot-features-application-exit"></a>
248
+
249
+ # ## 23.9、应用程序退出
250
+
251
+ 每个 `SpringApplication` 注册了一个 JVM 关闭钩子,以确保 `ApplicationContext` 在退出时可以优雅关闭。所有标准的 Spring 生命周期回调(比如 `DisposableBean` 接口,或者 `@PreDestroy` 注解)都可以使用。
252
+
253
+ 此外,如果希望在调用 `SpringApplication.exit()` 时返回特定的退出码,则 bean 可以实现 `org.springframework.boot.ExitCodeGenerator` 接口。之后退出码将传递给 `System.exit()` 以将其作为状态码返回,如示例所示:
254
+
255
+ ` ` ` java
256
+ @SpringBootApplication
257
+ public class ExitCodeApplication {
258
+
259
+ @Bean
260
+ public ExitCodeGenerator exitCodeGenerator() {
261
+ return () -> 42;
262
+ }
263
+
264
+ public static void main(String[] args) {
265
+ System.exit(SpringApplication
266
+ .exit(SpringApplication.run(ExitCodeApplication.class, args)));
267
+ }
268
+
269
+ }
270
+ ` ` `
271
+
272
+ 此外,`ExitCodeGenerator` 接口可以通过异常实现。遇到这类异常时,Spring Boot 将返回实现的 `getExitCode()` 方法提供的退出码。
273
+
274
+ <a id="boot-features-application-admin"></a>
275
+
276
+ # ## 23.10、管理功能
277
+
278
+ 可以通过指定 `spring.application.admin.enabled` 属性来为应用程序启用管理相关的功能。其将在 `MBeanServer` 平台上暴露 [`SpringApplicationAdminMXBean`](https://github.com/spring-projects/spring-boot/tree/v2.1.1.RELEASE/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/admin/SpringApplicationAdminMXBean.java)。您可以使用此功能来远程管理 Spring Boot 应用。该功能对服务包装器的实现也是非常有用的。
279
+
280
+ **提示**
281
+
282
+ > 如果您想知道应用程序在哪一个 HTTP 端口上运行,请使用 `local.server.port` 键获取该属性。
283
+
284
+ **注意**
285
+
286
+ > 启用此功能时请小心,因为 MBean 暴露了关闭应用程序的方法。
287
+
288
+ <a id="boot-features-external-config"></a>
289
+
290
+ # # 24、外部化配置
291
+
292
+ Spring Boot 可以让您的配置外部化,以便可以在不同环境中使用相同的应用程序代码。您可以使用 properties 文件、YAML 文件、环境变量或者命令行参数来外部化配置。可以使用 `@Value` 注解将属性值直接注入到 bean 中,可通过 Spring 的 `Environment` 访问,或者通过 `@ConfigurationProperties` 绑定到[结构化对象](#boot-features-external-config-typesafe-configuration-properties)。
293
+
294
+ Spring Boot 使用了一个非常特别的 `PropertySource` 指令,用于智能覆盖默认值。属性将按照以下顺序处理:
295
+
296
+ 1. 在您的主目录(当 devtools 被激活,则为 `~/.spring-boot-devtools.properties` )中的 [Devtools 全局设置属性](#using-boot-devtools-globalsettings)。
297
+ 2. 在测试中使用到的 `@TestPropertySource` 注解。
298
+ 3. 在测试中使用到的 `properties` 属性,可以是 [`@SpringBootTest`](https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/api/org/springframework/boot/test/context/SpringBootTest.html) 和[用于测试应用程序某部分的测试注解](#boot-features-testing-spring-boot-applications-testing-autoconfigured-tests)。
299
+ 4. 命令行参数。
300
+ 5. 来自 `SPRING_APPLICATION_JSON` 的属性(嵌入在环境变量或者系统属性【system propert】中的内联 JSON)。
301
+ 6. `ServletConfig` 初始化参数。
302
+ 7. `ServletContext` 初始化参数。
303
+ 8. 来自 `java:comp/env` 的 JNDI 属性。
304
+ 9. Java 系统属性(`System.getProperties()`)。
305
+ 10. 操作系统环境变量。
306
+ 11. 只有 `random.*` 属性的 `RandomValuePropertySource`。
307
+ 12. 在已打包的 jar 外部的[指定 profile 的应用属性文件](#boot-features-external-config-profile-specific-properties)(`application-{profile}.properties` 和 YAML 变量)。
308
+ 13. 在已打包的 jar 内部的[指定 profile 的应用属性文件](#boot-features-external-config-profile-specific-properties)(`application-{profile}.properties` 和 YAML 变量)。
309
+ 14. 在已打包的 jar 外部的应用属性文件(`application.properties` 和 YAML 变量)。
310
+ 15. 在已打包的 jar 内部的应用属性文件(`application.properties` 和 YAML 变量)。
311
+ 16. 在 `@Configuration` 类上的 `@PropertySource` 注解。
312
+ 17. 默认属性(使用 `SpringApplication.setDefaultProperties` 指定)。
313
+
314
+ 举个例子,假设开发的 `@Component` 使用了 `name` 属性,可以这样:
315
+
316
+ ` ` ` java
317
+ import org.springframework.stereotype.*;
318
+ import org.springframework.beans.factory.annotation.*;
319
+
320
+ @Component
321
+ public class MyBean {
322
+
323
+ @Value("${name}")
324
+ private String name;
325
+
326
+ // ...
327
+
328
+ }
329
+ ` ` `
330
+
331
+ 在您的应用程序的 classpath 中(比如在 jar 中),您可以有一个 `application.properties`,它为 `name` 提供了一个合适的默认属性值。当在新环境中运行时,您可以在 jar 外面提供一个 `application.properties` 来覆盖 `name`。对于一次性测试,您可以使用命令行指定形式启动(比如 `java -jar app.jar --name="Spring"`)。
332
+
333
+ **提示**
334
+
335
+ > `SPRING_APPLICATION_JSON` 属性可以在命令行中提供一个环境变量。比如在 UN*X shell 中:
336
+ ```
337
+ $$ SPRING_APPLICATION_JSON='{"acme":{"name":"test"}}' java -jar myapp.jar
338
+ ```
339
+ > 在此示例中,您可以在 Spring `Environment` 中使用 `acme.name=test`,也可以在系统属性(System property)中将 JSON 以 `spring.application.json` 属性提供:
340
+ ```
341
+ $ java -Dspring.application.json='{"name":"test"}' -jar myapp.jar
342
+ ```
343
+ 或者以命令行参数形式:
344
+ ```
345
+ $ java -jar myapp.jar --spring.application.json='{"name":"test"}'
346
+ ```
347
+ 或者将 JSON 作为一个 JNDI 变量:`java:comp/env/spring.application.json`。
348
+
106
349
**待续……**
0 commit comments