1. Spring Cloud 上下文:应用程序上下文服务
Spring Boot 对如何使用 Spring 构建应用程序有一种固执己见的看法。 例如,它具有用于常见配置文件的常规位置,并具有用于常见管理和监控任务的终端节点。 Spring Cloud 在此基础上构建,并添加了系统中许多组件会使用或偶尔需要的一些功能。
1.1. Bootstrap 应用程序上下文
Spring Cloud 应用程序通过创建“引导”上下文来运行,该上下文是主应用程序的父上下文。
此上下文负责从外部源加载配置属性,并解密本地外部配置文件中的属性。
这两个上下文共享一个Environment
,这是任何 Spring 应用程序的外部属性的来源。
默认情况下,引导程序属性(不是bootstrap.properties
但是在 bootstrap 阶段加载的属性)以高优先级添加,因此它们不能被本地配置覆盖。
引导程序上下文使用与主应用程序上下文不同的约定来查找外部配置。
而不是application.yml
(或.properties
),您可以使用bootstrap.yml
,将 bootstrap 和 main 上下文的外部配置很好地分开。
下面的清单显示了一个示例:
spring: application: name: foo cloud: config: uri: ${SPRING_CONFIG_URI:http://localhost:8888}
如果您的应用程序需要来自服务器的任何特定于应用程序的配置,最好将spring.application.name
(在bootstrap.yml
或application.yml
).
对于物业spring.application.name
要用作应用程序的上下文 ID,您必须在bootstrap.[properties | yml]
.
如果要检索特定的配置文件配置,还应将spring.profiles.active
在bootstrap.[properties | yml]
.
您可以通过设置spring.cloud.bootstrap.enabled=false
(例如,在 System Properties 中)。
1.2. 应用程序上下文层次结构
如果您从SpringApplication
或SpringApplicationBuilder
时,Bootstrap 上下文将作为父项添加到该上下文。
Spring 的一个功能是子上下文从其父上下文继承属性源和配置文件,因此与在没有 Spring Cloud Config 的情况下构建相同的上下文相比,“主”应用程序上下文包含额外的属性源。
其他属性源包括:
-
“bootstrap”:如果有
PropertySourceLocators
在 Bootstrap 上下文中找到,如果它们具有非空属性,则可选的CompositePropertySource
以高优先级显示。 一个例子是 Spring Cloud Config Server 中的属性。 有关如何自定义此属性源的内容,请参阅“自定义 Bootstrap 属性源”。
Spring Cloud 2021.0.8 之前的版本PropertySourceLocators (包括 Spring Cloud Config 的 API 的
主应用程序上下文,而不是 Bootstrap 上下文中。您可以强制PropertySourceLocators 在
通过设置 Bootstrap 上下文spring.cloud.config.initialize-on-context-refresh=true 在bootstrap.[properties | yaml] . |
-
“applicationConfig: [classpath:bootstrap.yml]”(如果 Spring 配置文件处于活动状态,则为相关文件):如果您有一个
bootstrap.yml
(或.properties
),这些属性用于配置 Bootstrap 上下文。 然后,当设置其 parent 时,它们将被添加到 child context 中。 它们的优先级低于application.yml
(或.properties
)以及作为创建 Spring Boot 应用程序过程的正常部分添加到子级的任何其他属性源。 有关如何自定义这些属性源的内容,请参阅“更改 Bootstrap 属性的位置”。
由于属性源的排序规则,“bootstrap” 条目优先。
但是,请注意,这些不包含来自bootstrap.yml
,它的优先级非常低,但可用于设置默认值。
您可以通过设置任何ApplicationContext
您可以创建 — 例如,通过使用它自己的接口或使用SpringApplicationBuilder
便捷方法 (parent()
,child()
和sibling()
).
引导程序上下文是您自己创建的最高级祖先的父级。
层次结构中的每个上下文都有自己的 “bootstrap” (可能为空) 属性源,以避免无意中将值从父级提升到其后代。
如果存在配置服务器,则层次结构中的每个上下文也可以(原则上)具有不同的spring.application.name
因此,使用不同的远程属性源。
正常的 Spring 应用程序上下文行为规则适用于属性解析:子上下文中的属性会覆盖
父级、按名称以及按属性源名称。
(如果子项具有与父项同名的属性源,则父项的值不包含在子项中)。
请注意,SpringApplicationBuilder
允许您共享Environment
在整个层次结构中,但这不是默认设置。
因此,同级上下文 (特别是) 不需要具有相同的配置文件或属性源,即使它们可能与其父级共享公共值。
1.3. 更改 Bootstrap 属性的位置
这bootstrap.yml
(或.properties
) 位置可以通过设置spring.cloud.bootstrap.name
(默认:bootstrap
),spring.cloud.bootstrap.location
(默认值:空)或spring.cloud.bootstrap.additional-location
(默认值:空) — 例如,在 System properties 中。
这些属性的行为类似于spring.config.*
变体。
跟spring.cloud.bootstrap.location
默认位置将被替换,并且仅使用指定的位置。
要将位置添加到默认位置列表中,spring.cloud.bootstrap.additional-location
可以使用。
实际上,它们用于设置 bootstrapApplicationContext
通过在其Environment
.
如果存在活动配置文件(来自spring.profiles.active
或通过Environment
API),该配置文件中的属性也会加载,与常规 Spring Boot 应用程序中的属性相同 — 例如,从bootstrap-development.properties
对于development
轮廓。
1.4. 覆盖 Remote Properties 的值
引导程序上下文添加到应用程序的属性源通常是“远程”(例如,来自 Spring Cloud Config Server)。
默认情况下,它们不能在本地覆盖。
如果你想让你的应用程序用它们自己的系统属性或配置文件覆盖远程属性,远程属性源必须通过设置spring.cloud.config.allowOverride=true
(在本地设置此项不起作用)。
设置该标志后,两个更细粒度的设置将控制远程属性相对于系统属性和应用程序本地配置的位置:
-
spring.cloud.config.overrideNone=true
:从任何本地属性源覆盖。 -
spring.cloud.config.overrideSystemProperties=false
:只有系统属性、命令行参数和环境变量(但不包括本地配置文件)应覆盖远程设置。
1.5. 自定义 Bootstrap 配置
引导上下文可以设置为执行任何您喜欢的作,方法是将条目添加到/META-INF/spring.factories
在名为org.springframework.cloud.bootstrap.BootstrapConfiguration
.
这包含以逗号分隔的 Spring 列表@Configuration
用于创建上下文的类。
可以在此处创建任何希望可用于主应用程序上下文以进行自动装配的 bean。
有一个特殊的合同@Beans
的类型ApplicationContextInitializer
.
如果要控制启动顺序,可以使用@Order
annotation (默认顺序为last
).
添加自定义BootstrapConfiguration ,请注意您添加的类不是@ComponentScanned 错误地进入您的 “main” 应用程序上下文,在那里可能不需要它们。
为引导配置类使用单独的软件包名称,并确保该名称尚未包含在@ComponentScan 或@SpringBootApplication 带注释的配置类。 |
引导过程通过将初始化器注入 mainSpringApplication
实例(这是正常的 Spring Boot 启动序列,无论它是作为独立应用程序运行还是部署在应用程序服务器中)。
首先,从spring.factories
.
然后,所有@Beans
的类型ApplicationContextInitializer
添加到主SpringApplication
在启动之前。
1.6. 自定义 Bootstrap 属性源
引导过程添加的外部配置的默认属性源是 Spring Cloud Config Server,但您可以通过添加 bean 类型的 bean 来添加其他源PropertySourceLocator
到 Bootstrap 上下文(通过spring.factories
).
例如,您可以插入来自不同服务器或数据库的其他属性。
例如,请考虑以下自定义定位器:
@Configuration
public class CustomPropertySourceLocator implements PropertySourceLocator {
@Override
public PropertySource<?> locate(Environment environment) {
return new MapPropertySource("customProperty",
Collections.<String, Object>singletonMap("property.from.sample.custom.source", "worked as intended"));
}
}
这Environment
,则传入的ApplicationContext
即将创建 — 换句话说,我们为其提供其他属性源的那个。
它已经具有 Spring Boot 提供的常规属性源,因此您可以使用这些属性源来查找特定于此的属性源Environment
(例如,通过将其键入spring.application.name
,就像在默认的 Spring Cloud Config Server 属性源定位器中所做的那样)。
如果您创建一个包含此类的 jar,然后添加一个META-INF/spring.factories
包含以下设置,customProperty
PropertySource
出现在在其 Classpath 中包含该 jar 的任何应用程序中:
org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator
从 Spring Cloud 2021.0.8 开始,Spring Cloud 现在将调用PropertySourceLocators
两次。第一次 fetch
将检索不带任何配置文件的任何属性源。这些属性来源将有机会
使用以下方式激活配置文件spring.profiles.active
.主应用程序上下文启动后PropertySourceLocators
将再次调用,这一次任何活动配置文件都允许PropertySourceLocators
查找
任何其他PropertySources
与配置文件。
1.7. 日志记录配置
如果使用 Spring Boot 配置日志设置,则应将此配置放在bootstrap.[yml | properties]
如果您希望它适用于所有事件。
要使 Spring Cloud 正确初始化日志记录配置,您不能使用自定义前缀。
例如,使用custom.loggin.logpath 在初始化日志记录系统时,Spring Cloud 无法识别。 |
1.8. 环境更改
应用程序侦听EnvironmentChangeEvent
并以几种标准方式对更改做出反应(附加ApplicationListeners
可以添加为@Beans
以正常方式)。
当EnvironmentChangeEvent
时,它有一个已更改的键值列表,应用程序使用这些值来:
-
重新绑定任何
@ConfigurationProperties
bean 的 bean 中。 -
为 中的任何属性设置 Logger 级别
logging.level.*
.
请注意,默认情况下,Spring Cloud Config Client 不会轮询Environment
.
通常,我们不建议使用这种方法来检测更改(尽管您可以使用@Scheduled
注释)。
如果您有一个横向扩展的客户端应用程序,最好将EnvironmentChangeEvent
到所有实例,而不是让它们轮询更改(例如,通过使用 Spring Cloud Bus)。
这EnvironmentChangeEvent
涵盖了一大类刷新用例,只要您实际上可以更改Environment
并发布事件。
请注意,这些 API 是公共的,并且是核心 Spring 的一部分。
您可以验证更改是否绑定到@ConfigurationProperties
beans 的访问/configprops
endpoint(Spring Boot Actuator 的标准功能)。
例如,DataSource
可以具有其maxPoolSize
在运行时更改(默认的DataSource
由 Spring Boot 创建的是一个@ConfigurationProperties
bean) 并动态增加容量。
重新绑定@ConfigurationProperties
没有涵盖另一大类用例,在这些用例中,您需要对刷新进行更多控制,并且需要对整个ApplicationContext
.
为了解决这些问题,我们采取了@RefreshScope
.
1.9. 刷新范围
当配置发生更改时,Spring@Bean
标记为@RefreshScope
得到特殊待遇。
此功能解决了有状态 Bean 仅在初始化时注入其配置的问题。
例如,如果DataSource
在通过Environment
,您可能希望这些连接的持有者能够完成他们正在执行的作。
然后,下次从池中借用连接时,它会获得一个具有新 URL 的连接。
有时,甚至可能强制应用@RefreshScope
注解,这些 bean 只能初始化一次。
如果 bean 是 “不可变的”,则必须使用@RefreshScope
或在 property 键下指定 classname:spring.cloud.refresh.extra-refreshable
.
如果你有一个DataSource bean 是一个HikariDataSource ,则不能
刷新。它是spring.cloud.refresh.never-refreshable .选择一个
不同DataSource implementation (如果需要刷新)。 |
刷新范围 bean 是惰性代理,它们在使用时(即调用方法时)进行初始化,并且范围充当初始化值的缓存。 要强制 Bean 在下一次方法调用时重新初始化,必须使其高速缓存条目无效。
这RefreshScope
是上下文中的 Bean,并且具有公共refreshAll()
方法通过清除目标缓存来刷新作用域中的所有 bean。
这/refresh
endpoint 公开此功能(通过 HTTP 或 JMX)。
要按名称刷新单个 Bean,还有一个refresh(String)
方法。
要公开/refresh
endpoint,您需要将以下配置添加到您的应用程序中:
management:
endpoints:
web:
exposure:
include: refresh
@RefreshScope (技术上)在@Configuration 类,但它可能会导致令人惊讶的行为。
例如,这并不意味着所有@Beans 定义在那个类中,他们自己都在@RefreshScope .
具体来说,任何依赖于这些 bean 的东西都不能依赖于在启动刷新时更新它们,除非它本身在@RefreshScope .
在这种情况下,它会在刷新时重新构建,并且其依赖项会重新注入。
此时,它们将从刷新的@Configuration ). |
删除配置值,然后执行刷新不会更新配置值的存在。 必须存在 configuration 属性,才能在刷新后更新值。如果您依赖于 应用程序中的一个值,您可能希望切换逻辑以依赖它的缺失。另一种选择是依赖 值更改而不是不存在于应用程序的配置中。 |
1.10. 加密和解密
Spring Cloud 有一个Environment
用于在本地解密属性值的预处理器。
它遵循与 Spring Cloud Config Server 相同的规则,并通过encrypt.*
.
因此,您可以使用{cipher}*
,并且只要存在有效密钥,它们就会在主应用程序上下文获取Environment
设置。
要在应用程序中使用加密功能,您需要在类路径中包含 Spring Security RSA(Maven 坐标:org.springframework.security:spring-security-rsa
),并且您还需要在 JVM 中提供全功能 JCE 扩展。
如果由于“非法密钥大小”而出现异常,并且使用 Sun 的 JDK,则需要安装 Java 加密扩展 (JCE) 无限强度管辖策略文件。 有关更多信息,请参阅以下链接:
将文件解压缩到您使用的任何 JRE/JDK x64/x86 版本的 JDK/jre/lib/security 文件夹中。
1.11. 终端节点
对于 Spring Boot Actuator 应用程序,可以使用一些额外的 Management 端点。您可以使用:
-
POST
自/actuator/env
要更新Environment
并重新绑定@ConfigurationProperties
和日志级别。 要启用此终端节点,您必须设置management.endpoint.env.post.enabled=true
. -
/actuator/refresh
要重新加载引导带上下文并刷新@RefreshScope
豆。 -
/actuator/restart
以关闭ApplicationContext
并重新启动它(默认处于禁用状态)。 -
/actuator/pause
和/actuator/resume
调用的Lifecycle
方法 (stop()
和start()
在ApplicationContext
).
如果禁用/actuator/restart 端点,则/actuator/pause 和/actuator/resume 端点
也会被禁用,因为它们只是/actuator/restart . |