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