spring cloud连载第一篇之bootstrap context
1. Spring Cloud Context: Application Context Services(应用上下文服务)
1.1 The Bootstrap Application Context(引导上下文)
一个spring cloud应用会创建一个“bootstrap”context,它是主应用的parent context。它负责加载外部资源的配置属性并且解释本地外部配置文件中的属性。
这里有两个context,一个是spring boot的main context,另一个是spring cloud的bootstrap context,这两个context共享同一个环境,也就是说他们共享spring项目的外部配置属性。
默认情况下,bootstrap属性(并非是bootstrap.properties而是那些在bootstrap阶段加载的属性)是以高优先级的方式添加的,所以无法被本地配置覆盖。
bootstrap context和main context使用不同的方法定位外部配置,你可以使用bootstrap.yml来替代application.yml来为bootstrap context添加配置,这样就可以区分开bootstrap context和main context。
可以通过在系统属性中设置spring.cloud.bootstrap.enabled=false来禁用bootstrap程序。
1.2 Application Context Hierarchies(应用上下文层级)
如果你通过SpringApplication或者SpringApplicationBuilder构建了一个application context,那么bootstrap context将会作为它的parent context被添加。
spring的一个特性是child context会从它的parent context中继承属性资源和配置文件,因此main application context有一些额外的属性资源:
“bootstrap”:如果在bootstrap context中发现PropertySourceLocators并且含有非空属性,那么一个CompositePropertySource将会以高优先级出现。
“applicationConfig”:如果你有一个bootstrap.yml,并且设置了配置bootstrap context的属性,那么它们将会被添加到child context中。但是它们具有比application.yml或者其他配置更低的优先级。
由于资源属性的排序规则,“bootstrap”入口具有高优先级。注意这不包括bootstrap.yml中的数据(具有较低优先级,可以用来设置默认属性)。
1.3 Changing the Location of Bootstrap Properties
bootstrap.yml可以通过在系统属性中设置spring.cloud.bootstrap.name或者spring.cloud.bootstrap.location来指定。
如果有一个激活的配置文件(通过spring.profiles.active或者Environment API设置),那么这些文件中的属性都会被加载。
1.4 Overriding the Values of Remote Properties(覆盖远程属性的值)
通过bootstrap context添加到应用中的属性资源可能经常是“远程”的,例如从Spring Cloud Config Server读取的属性。默认情况下,他们不能被本地覆盖。
如果你希望让你的应用通过系统属性或者本地配置来重写那些远程配置,可以通过设置远程属性资源spring.cloud.config.allowOverride=true(在本地设置无效)。
一旦设置了上面的标志,就可以通过下面两个远程属性来控制远程属性和系统属性跟本地配置的关系:
spring.cloud.config.overrideNone=true:远程属性可以被本地任意属性资源覆盖
spring.cloud.config.overrideSystemProperties=false:仅仅系统属性,命令行参数和环境变量(不包括配置文件)可以覆盖远程设置。
1.5 Customizing the Bootstrap Configuration(自定义bootstrap配置)
bootstrap context可以被设置来做任何你想要做的事,只要在/META-INF/spring.factories文件中配置org.springframework.cloud.bootstrap.BootstrapConfiguration的值即可。
它的值是以逗号分隔的@Configuration类的全限定名。所以任何你想要在main application context中注入的bean都可以在这里配置。如果你希望控制启动顺序,在类上添加@Order注解(默认顺序为最后)。
注意:不要bootstrap配置被main context加载到,即不能被@ComponentScan和@SpringBootApplication注解的配置类覆盖到。
bootstrap程序最后将初始化器注入到main SpringApplication实例中。首先,通过spring.factories中配置的类来创建bootstrap context,然后所有ApplicationContextInitializer的bean将会被添加到main SpringApplication中,在其启动前。
1.6 Customizing the Bootstrap Property Sources(定制化bootstrap属性资源)
通过bootstrap程序添加的外部配置的默认属性资源是Spring Cloud Config Server。但是可以通过添加PropertySourceLocator类型的bean到bootstrap context中(通过spring.factories)来添加额外的资源。
举个🌰:
1 @Configuration 2 public class CustomPropertySourceLocator implements PropertySourceLocator { 3 4 @Override 5 public PropertySource<?> locate(Environment environment) { 6 return new MapPropertySource("customProperty", 7 Collections.<String, Object>singletonMap("property.from.sample.custom.source", "worked as intended")); 8 } 9 10 }
然后在META-INF/spring.factories
文件中添加
1 org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator
1.7 Refresh Scope(刷新域)
当配置改变时,被标记为@RefreshScope的bean会得到一些特殊对待。这个特性将会解决一些beans在仅仅在初始化时注入配置的问题。
例如,数据库url改变时,数据源已经打开了一些数据库连接,你可能希望那些已经打开的连接能够将他们的工作完成,但是当有新的请求来获取连接时,返回给他们新的url连接。
有时可能需要强制性的在一些只能初始化一次的bean上添加@RefreshScope注解。如果一个bean是“不可变的”,你将不得不为它添加@RefreshScope注解或者在spring.cloud.refresh.extra-refreshable键上指定class name。
处在refresh scope中的bean是延迟代理,只有当他们被使用时才初始化,并且这个scope像是一个已初始化值的缓存。为了能使bean在下次使用时重新初始化,必须将它的缓存入口置为无效。
RefreshScope是一个bean,并且有一个公共方法refreshAll(),这个方法通过清理目标缓存的手段来达到刷新在scope中的所有bean。
端点/refresh向外部提供了这个功能(通过HTTP或者JMX)。如果想通过bean的名称来刷新bean可以使用refresh(String)方法。
要向外暴露/refresh端点,需要在配置文件中写入以下配置:
1 management: 2 endpoints: 3 web: 4 exposure: 5 include: refresh
注意:@RefreshScope在@Configuration的类上起作用,但可能有一些特殊的行为。比如说,并不意味着所有在@Configuration类中定义的bean都是在@RefreshScope中的。所以任何依赖那些bean的东西都不能在刷新时得到
更新。
1.8 Endpoints(端点)
如果你的应用是一个Spring Boot Actuator 那么会有一些额外的管理端点:
发送一个POST请求到/actuator/env可以更新Environment,重新绑定@ConfigurationProperties
和日志级别;
/actuator/refresh重新加载bootstrap context并且刷新@RefreshScope中的bean;
/actuator/restart重新启动ApplicationContext(默认此功能是关闭的);
/actuator/pause和/actuator/resume是在ApplicationContext上调用生命周期方法stop()和start()
注意:如果禁止了/actuator/restart端点那么/actuator/pause和/actuator/resume也会被禁止。