The Bootstrap Application Context (引导应用程序上下文)
一个Spring Cloud应用程序通过创建一个“引导”上下文来进行操作,这个上下文是主应用程序的父上下文。
开箱即用,负责从外部源加载配置属性,还解密本地外部配置文件中的属性。
这两个上下文共享一个
Environment
,这是任何Spring应用程序的外部属性的来源。
Bootstrap属性的优先级高,因此默认情况下不能被本地配置覆盖。
引导上下文使用与主应用程序上下文不同的外部配置约定,因此使用
bootstrap.yml
、
application.yml
或
application.properties
项目中配置代替引导和主上下文的外部配置。例:
bootstrap.yml
spring: application: name: foo cloud: config: uri: ${SPRING_CONFIG_URI:http://localhost:8888}
如果您的应用程序需要服务器上的特定于应用程序的配置,那么设置spring.application.name(在bootstrap.yml或application.yml)中是个好主意。
您可以通过设置spring.cloud.bootstrap.enabled=false(例如在系统属性中)来完全禁用引导过程。
Application Context Hierarchies(应用程序上下文层次结构)
如果您从SpringApplication或SpringApplicationBuilder构建应用程序上下文,则将Bootstrap上下文添加为该上下文的父级。
这是一个Spring的功能,即子上下文从其父进程继承属性源和配置文件,因此与不使用Spring Cloud Config构建相同上下文相比,“主”应用程序上下文将包含其他属性源。额外的财产来源是:
- “bootstrap”:如果在Bootstrap上下文中找到任何PropertySourceLocators,则可选CompositePropertySource显示为高优先级,并且具有非空属性。
一个例子是来自Spring Cloud Config服务器的属性。
- “applicationConfig:[classpath:bootstrap.yml]”(如果Spring配置文件处于活动状态,则为朋友)。如果您有一个bootstrap.yml(或属性),那么这些属性用于配置引导上下文,然后在父进程设置时将它们添加到子上下文中。它们的优先级低于application.yml(或.properties)以及作为创建Spring Boot应用程序的过程的正常部分添加到子级的任何其他属性源。
由于属性源的排序规则,“bootstrap”条目优先,但请注意,这些条目
不包含来自bootstrap.yml的任何数据,它具有非常低的优先级,但可用于设置默认值
。
z-ps:
bootstrap.yml 和application.yml 都可以用来配置参数
bootstrap.yml可以理解成系统级别的一些参数配置,这些参数一般是不会变动的(Spring cloud)
application.yml 可以用来定义应用级别的,如果搭配spring-cloud-config使用 application.yml里面定义的文件可以实现动态替换
您可以通过简单地设置您创建的任何ApplicationContext的父上下文来扩展上下文层次结构,例如使用自己的界面,或使用SpringApplicationBuilder方便方法(parent(),child()和sibling())。
z-ps:
如果SpringApplication无法满足要求,你可以自己创建一个局部实例,然后对其进行设置:
public static void main(String[] args) { SpringApplication app = new SpringApplication(MySpringConfiguration.class); //关闭Banner打印 app.setBannerMode(Banner.Mode.OFF); //添加监听器 app.addListeners(new MyListener()); ... app.run(args);}
SpringApplication的相关配置将会被@Configuration注解的类,XML配置文件,以及Spring扫描的包引用。
你也可以通过SpringApplicationBuilder来对SpringApplication的属性进行配置,这样的结构更有层次感。SpringApplicationBuilder为构 建
SpringApplication
和
ApplicationContext
实例提供了一套便利的流式API:
new SpringApplicationBuilder() .sources(Parent.class) .child(Application.class) .bannerMode(Banner.Mode.OFF) .listeners(new MyListener()) ... .run(args);
SpringApplication将会根据需要创建一个ApplicationContext,默认情况下,如果是非web应用,则会创建一个AnnotationConfigApplicationContext上下文,如果是web应用,则会创建一个AnnotationConfigEmbeddedWebApplicationContext上下文。当然,你也可以通过setWebEnvironment(boolean webEnvironment)来覆盖默认的设置
。
引导环境将是您创建自己的最高级祖先的父级。层次结构中的每个上下文都将有自己的“bootstrap”属性源(可能为空),以避免无意中将值从父级升级到其后代。层次结构中的每个上下文(原则上)也可以具有不同的spring.application.name,因此如果存在配置服务器,则不同的远程属性源。
普通的Spring应用程序上下文行为规则适用于属性解析:子环境中的属性通过名称和属性源名称覆盖父项中的属性(如果子级具有与父级名称相同的属性源,一个来自父母的孩子不包括在孩子中)。
请注意,SpringApplicationBuilder允许您在整个层次结构中共享Environment,但这不是默认值。因此,尤其不需要具有相同的资料或财产来源,尽管它们与父级共享共同点。
Changing the Location of Bootstrap Properties(改变引导位置Properties)
可以使用
spring.cloud.bootstrap.name
(默认“bootstrap”)或
spring.cloud.bootstrap.location
(默认为空)指定
bootstrap.yml
(或
.properties
)位置,例如在系统属性中。这些属性的行为类似于具有相同名称的
spring.config.*
变体,实际上它们用于通过在其
Environment
中设置这些属性来设置引导
ApplicationContext
。如果在正在构建的上下文中有活动的配置文件(来自
spring.profiles.active
或通过
Environment
API)),则该配置文件中的属性也将被加载,就像常规的Spring Boot应用程序,例如来自
bootstrap-development.properties
的“develop”配置,根据不同的环境配置不同的字段属性。
Customizing the Bootstrap Configuration(自定义引导配置)
可以通过在org.springframework.cloud.bootstrap.BootstrapConfiguration键下添加条目/META-INF/spring.factories来训练引导上下文来执行任何您喜欢的操作。这是用于创建上下文的Spring @Configuration类的逗号分隔列表。您可以在此处创建要用于自动装配的主应用程序上下文的任何bean,并且还有ApplicationContextInitializer类型的@Beans的特殊合同。如果要控制启动顺序(默认顺序为“最后”),可以使用@Order标记类。
@SpringBootApplication
(scanBasePackages = {
"com.o2b"
,
"com.o2c"
})
引导过程通过将初始化器注入主SpringApplication实例(即正常的Spring Boot启动顺序,无论是作为独立应用程序运行还是部署在应用程序服务器中)结束。首先,从spring.factories中找到的类创建引导上下文,然后在ApplicationContextInitializer类型的所有@Beans添加到主SpringApplication开始之前
Customizing the Bootstrap Property Sources(
自定义引导属性源
)
引导过程添加的外部配置的默认属性源是Config Server,但您可以通过将PropertySourceLocator类型的bean添加到引导上下文(通过spring.factories)添加其他源。您可以使用此方法从其他服务器或数据库中插入其他属性。
作为一个例子,请考虑以下自定义定位器:
@Configurationpublic 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的Environment,即为我们提供额外的属性来源的。它将已经具有正常的Spring Boot提供的资源来源,因此您可以使用它们来定位特定于此Environment的属性源(例如通过将其绑定在spring.application.name上,如在默认情况下所做的那样Config Server属性源定位器)。
如果你在这个类中创建一个jar,然后添加一个META-INF/spring.factories包含:
org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator
那么“customProperty”PropertySource将显示在其类路径中包含该jar的任何应用程序中。
环境变化
应用程序将监听EnvironmentChangeEvent,并以几种标准方式进行更改(用户可以以常规方式添加ApplicationListeners附加ApplicationListeners)。当观察到EnvironmentChangeEvent时,它将有一个已更改的键值列表,应用程序将使用以下内容:
- 重新绑定上下文中的任何@ConfigurationProperties bean
- 为logging.level.*中的任何属性设置记录器级别
请注意,配置客户端不会通过默认轮询查找Environment中的更改,通常我们不建议检测更改的方法(尽管可以使用@Scheduled注释进行设置)。如果您有一个扩展的客户端应用程序,那么最好将EnvironmentChangeEvent广播到所有实例,而不是让它们轮询更改(例如使用
Spring Cloud总线
)。
EnvironmentChangeEvent涵盖了大量的刷新用例,只要您真的可以更改Environment并发布事件(这些API是公开的,部分内核为Spring)。您可以通过访问/configprops端点(普通Spring Boot执行器功能)来验证更改是否绑定到@ConfigurationProperties bean。例如,DataSource可以在运行时更改其maxPoolSize(由Spring Boot创建的默认DataSource是一个@ConfigurationProperties bean),并且动态增加容量。重新绑定@ConfigurationProperties不会覆盖另一大类用例,您需要更多的控制刷新,并且您需要更改在整个ApplicationContext上是原子的。为了解决这些担忧,我们有@RefreshScope。
刷新范围
当配置更改时,标有@RefreshScope的Spring @Bean将得到特殊处理。这解决了状态bean在初始化时只注入配置的问题。例如,如果通过Environment更改数据库URL时DataSource有开放连接,那么我们可能希望这些连接的持有人能够完成他们正在做的工作。然后下一次有人从游泳池借用一个连接,他得到一个新的URL。
刷新范围bean是在使用时初始化的懒惰代理(即当调用一个方法时),并且作用域作为初始值的缓存。要强制bean重新初始化下一个方法调用,您只需要使其缓存条目无效。
RefreshScope是上下文中的一个bean,它有一个公共方法refreshAll()来清除目标缓存中的范围内的所有bean。还有一个refresh(String)方法可以按名称刷新单个bean。此功能在/refresh端点(通过HTTP或JMX)中公开。