Spring 的@RefreshScope 坏了还是我用错了?
Is Spring's @RefreshScope broken or am I using it wrong?
我有一个 Spring 配置服务器 运行 @EnableConfigServer 并且工作正常
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
然后我还有客户端,运行 @SpringBootApplication 和@RefreshScope
@SpringBootApplication
@RefreshScope
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
以及我的 RestController
@RestController
@RefreshScope
public class LicenseServiceController {
@Value("${some.property}")
String someProperty;
@GetMapping("/someProperty")
public String getSomeProperty() {
return someProperty;
}
}
现在,我已经让 Config Server 与我的私有 github 存储库端点通信以检索配置属性,它做得非常好,例如,如果我访问了我的端点 http://localhost:8888/y/default,它会把这个片段还给我
propertySources: [
{
name: "https://github.com/me/config/x/y.yml",
source: {
some.property: "hi"
}
}
]
一切正常,当我从客户端通过@Value 标记访问使用属性 的端点时,我返回@Value(${some.property} )
问题是当我更新我的 git 存储库并将 some.property 更改为 "bye" 时。如果我再次从客户端访问端点,我将再次返回 "hi" 以获得 @Value(${some.property}) 而不是 "bye".
在配置服务器端点 http://localhost:8888/y/default,然后我得到
propertySources: [
{
name: "https://github.com/me/config/x/y.yml",
source: {
some.property: "bye"
}
}
]
虽然在客户端,我仍然得到 "hi" for @Value(${some.property})
即使我使用 POST 请求
从客户端访问 /actuators/refresh 端点
这是我从客户端 (SpringBootApplication) 获得的调试日志,在我看来 POST 请求有效,我从我的 c[=57= 得到了正确的响应] 命令也是如此,至少我认为
INFO 13493 --- [nio-8080-exec-2] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$b4dd7d61] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
INFO 13493 --- [nio-8080-exec-2] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://localhost:8888
DEBUG 13493 --- [nio-8080-exec-2] o.s.web.client.RestTemplate : Created GET request for "http://localhost:8888/y/default"
DEBUG 13493 --- [nio-8080-exec-2] o.s.web.client.RestTemplate : Setting request Accept header to [application/json, application/*+json]
DEBUG 13493 --- [nio-8080-exec-2] o.s.web.client.RestTemplate : GET request for "http://localhost:8888/y/default" resulted in 200 (null)
DEBUG 13493 --- [nio-8080-exec-2] o.s.web.client.RestTemplate : Reading [class org.springframework.cloud.config.environment.Environment] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@2e68f713]
INFO 13493 --- [nio-8080-exec-2] c.c.c.ConfigServicePropertySourceLocator : Located environment: name=y, profiles=[default], label=null, version=948c431771g06325k3520x67k70z74xa2829ts33, state=null
INFO 13493 --- [nio-8080-exec-2] b.c.PropertySourceBootstrapConfiguration : Located property source: CompositePropertySource {name='configService', propertySources=[MapPropertySource {name='configClient'}, MapPropertySource {name='https://github.com/me/tmp-config/x/y.yml'}]}
INFO 13493 --- [nio-8080-exec-2] o.s.boot.SpringApplication : The following profiles are active: default
INFO 13493 --- [nio-8080-exec-2] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@6a81dcff: startup date [Fri Jul 13 21:02:29 EDT 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@7ab876b9
INFO 13493 --- [nio-8080-exec-2] o.s.boot.SpringApplication : Started application in 0.202 seconds (JVM running for 24.359)
DEBUG 13493 --- [nio-8080-exec-2] o.s.w.c.s.StandardServletEnvironment : Replacing PropertySource 'bootstrapProperties' with 'bootstrapProperties'
DEBUG 13493 --- [nio-8080-exec-2] o.s.w.c.s.StandardServletEnvironment : Replacing PropertySource 'random' with 'random'
DEBUG 13493 --- [nio-8080-exec-2] o.s.w.c.s.StandardServletEnvironment : Replacing PropertySource 'applicationConfig: [classpath:/application.yml]' with 'applicationConfig: [classpath:/application.yml]'
DEBUG 13493 --- [nio-8080-exec-2] o.s.w.c.s.StandardServletEnvironment : Replacing PropertySource 'springCloudClientHostInfo' with 'springCloudClientHostInfo'
DEBUG 13493 --- [nio-8080-exec-2] o.s.w.c.s.StandardServletEnvironment : Replacing PropertySource 'applicationConfig: [classpath:/bootstrap.yml]' with 'applicationConfig: [classpath:/bootstrap.yml]'
DEBUG 13493 --- [nio-8080-exec-2] o.s.w.c.s.StandardServletEnvironment : Replacing PropertySource 'defaultProperties' with 'defaultProperties
DEBUG 13493 --- [nio-8080-exec-2] o.s.w.c.s.StandardServletEnvironment : Replacing PropertySource 'defaultProperties' with 'defaultProperties'
INFO 13493 --- [nio-8080-exec-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@6a81dcff: startup date [Fri Jul 13 21:02:29 EDT 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@7ab876b9
INFO 13493 --- [nio-8080-exec-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@7ab876b9: startup date [Fri Jul 13 21:02:29 EDT 2018]; root of context hierarchy
DEBUG 13493 --- [nio-8080-exec-2] m.m.a.RequestResponseBodyMethodProcessor : Written [[config.client.version, some.property]] as "application/vnd.spring-boot.actuator.v2+json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@67770b37]
DEBUG 13493 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
DEBUG 13493 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Successfully completed request
现在,我能得出的唯一结论是端点 url 是错误的,因为在日志中它显示“https://github.com/me/config/x/y.yml”
但在浏览器中给出 404,因为它应该是“https://github.com/me/config/blob/master/x/y.yml”,但这似乎是 Spring 作者不太可能出现的错误。好像我做的一切都是对的,但不知何故还是坏了
您应该刷新 bean,而不是尝试刷新整个应用程序,以及它加载的所有配置 > bean。
来自 Spring 文档,
https://cloud.spring.io/spring-cloud-static/docs/1.0.x/spring-cloud.html#_refresh_scope
@RefreshScope works (technically) on an @Configuration class, but it might lead to surprising behaviour: e.g. it does not mean that all the @Beans defined in that class are themselves @RefreshScope. Specifically, anything that depends on those beans cannot rely on them being updated when a refresh is initiated, unless it is itself in @RefreshScope (in which it will be rebuilt on a refresh and its dependencies re-injected, at which point they will be re-initialized from the refreshed @Configuration).
您应该做的是在值被注入的任何地方刷新 bean。
我有一个 Spring 配置服务器 运行 @EnableConfigServer 并且工作正常
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
然后我还有客户端,运行 @SpringBootApplication 和@RefreshScope
@SpringBootApplication
@RefreshScope
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
以及我的 RestController
@RestController
@RefreshScope
public class LicenseServiceController {
@Value("${some.property}")
String someProperty;
@GetMapping("/someProperty")
public String getSomeProperty() {
return someProperty;
}
}
现在,我已经让 Config Server 与我的私有 github 存储库端点通信以检索配置属性,它做得非常好,例如,如果我访问了我的端点 http://localhost:8888/y/default,它会把这个片段还给我
propertySources: [
{
name: "https://github.com/me/config/x/y.yml",
source: {
some.property: "hi"
}
}
]
一切正常,当我从客户端通过@Value 标记访问使用属性 的端点时,我返回@Value(${some.property} )
问题是当我更新我的 git 存储库并将 some.property 更改为 "bye" 时。如果我再次从客户端访问端点,我将再次返回 "hi" 以获得 @Value(${some.property}) 而不是 "bye".
在配置服务器端点 http://localhost:8888/y/default,然后我得到
propertySources: [
{
name: "https://github.com/me/config/x/y.yml",
source: {
some.property: "bye"
}
}
]
虽然在客户端,我仍然得到 "hi" for @Value(${some.property}) 即使我使用 POST 请求
从客户端访问 /actuators/refresh 端点这是我从客户端 (SpringBootApplication) 获得的调试日志,在我看来 POST 请求有效,我从我的 c[=57= 得到了正确的响应] 命令也是如此,至少我认为
INFO 13493 --- [nio-8080-exec-2] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$b4dd7d61] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
INFO 13493 --- [nio-8080-exec-2] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://localhost:8888
DEBUG 13493 --- [nio-8080-exec-2] o.s.web.client.RestTemplate : Created GET request for "http://localhost:8888/y/default"
DEBUG 13493 --- [nio-8080-exec-2] o.s.web.client.RestTemplate : Setting request Accept header to [application/json, application/*+json]
DEBUG 13493 --- [nio-8080-exec-2] o.s.web.client.RestTemplate : GET request for "http://localhost:8888/y/default" resulted in 200 (null)
DEBUG 13493 --- [nio-8080-exec-2] o.s.web.client.RestTemplate : Reading [class org.springframework.cloud.config.environment.Environment] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@2e68f713]
INFO 13493 --- [nio-8080-exec-2] c.c.c.ConfigServicePropertySourceLocator : Located environment: name=y, profiles=[default], label=null, version=948c431771g06325k3520x67k70z74xa2829ts33, state=null
INFO 13493 --- [nio-8080-exec-2] b.c.PropertySourceBootstrapConfiguration : Located property source: CompositePropertySource {name='configService', propertySources=[MapPropertySource {name='configClient'}, MapPropertySource {name='https://github.com/me/tmp-config/x/y.yml'}]}
INFO 13493 --- [nio-8080-exec-2] o.s.boot.SpringApplication : The following profiles are active: default
INFO 13493 --- [nio-8080-exec-2] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@6a81dcff: startup date [Fri Jul 13 21:02:29 EDT 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@7ab876b9
INFO 13493 --- [nio-8080-exec-2] o.s.boot.SpringApplication : Started application in 0.202 seconds (JVM running for 24.359)
DEBUG 13493 --- [nio-8080-exec-2] o.s.w.c.s.StandardServletEnvironment : Replacing PropertySource 'bootstrapProperties' with 'bootstrapProperties'
DEBUG 13493 --- [nio-8080-exec-2] o.s.w.c.s.StandardServletEnvironment : Replacing PropertySource 'random' with 'random'
DEBUG 13493 --- [nio-8080-exec-2] o.s.w.c.s.StandardServletEnvironment : Replacing PropertySource 'applicationConfig: [classpath:/application.yml]' with 'applicationConfig: [classpath:/application.yml]'
DEBUG 13493 --- [nio-8080-exec-2] o.s.w.c.s.StandardServletEnvironment : Replacing PropertySource 'springCloudClientHostInfo' with 'springCloudClientHostInfo'
DEBUG 13493 --- [nio-8080-exec-2] o.s.w.c.s.StandardServletEnvironment : Replacing PropertySource 'applicationConfig: [classpath:/bootstrap.yml]' with 'applicationConfig: [classpath:/bootstrap.yml]'
DEBUG 13493 --- [nio-8080-exec-2] o.s.w.c.s.StandardServletEnvironment : Replacing PropertySource 'defaultProperties' with 'defaultProperties
DEBUG 13493 --- [nio-8080-exec-2] o.s.w.c.s.StandardServletEnvironment : Replacing PropertySource 'defaultProperties' with 'defaultProperties'
INFO 13493 --- [nio-8080-exec-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@6a81dcff: startup date [Fri Jul 13 21:02:29 EDT 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@7ab876b9
INFO 13493 --- [nio-8080-exec-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@7ab876b9: startup date [Fri Jul 13 21:02:29 EDT 2018]; root of context hierarchy
DEBUG 13493 --- [nio-8080-exec-2] m.m.a.RequestResponseBodyMethodProcessor : Written [[config.client.version, some.property]] as "application/vnd.spring-boot.actuator.v2+json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@67770b37]
DEBUG 13493 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
DEBUG 13493 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Successfully completed request
现在,我能得出的唯一结论是端点 url 是错误的,因为在日志中它显示“https://github.com/me/config/x/y.yml”
但在浏览器中给出 404,因为它应该是“https://github.com/me/config/blob/master/x/y.yml”,但这似乎是 Spring 作者不太可能出现的错误。好像我做的一切都是对的,但不知何故还是坏了
您应该刷新 bean,而不是尝试刷新整个应用程序,以及它加载的所有配置 > bean。
来自 Spring 文档,
https://cloud.spring.io/spring-cloud-static/docs/1.0.x/spring-cloud.html#_refresh_scope
@RefreshScope works (technically) on an @Configuration class, but it might lead to surprising behaviour: e.g. it does not mean that all the @Beans defined in that class are themselves @RefreshScope. Specifically, anything that depends on those beans cannot rely on them being updated when a refresh is initiated, unless it is itself in @RefreshScope (in which it will be rebuilt on a refresh and its dependencies re-injected, at which point they will be re-initialized from the refreshed @Configuration).
您应该做的是在值被注入的任何地方刷新 bean。