SpringBoot / Spring Cloud Config Client带有RefreshScope注释的Bean的多个应用程序上下文(root和servlet)

时间:2018-08-02 21:24:24

标签: spring-boot spring-cloud spring-cloud-config

关于Web应用程序中的Spring Cloud Config,我有几个问题。

上下文

我正在使用一个SpringBoot Web应用程序,其中有一个 Root应用程序上下文(父级)和一个 Servlet应用程序上下文(子级),我要添加Spring此应用程序的Cloud Config功能(当然,此应用程序通过http连接到Spring Cloud Config服务器)。

当我用RefreshScope注释对在Root应用程序上下文中注册的bean进行注释时,一切都按预期进行,当我尝试对在Servlet应用程序上下文中注册的spring bean进行注释时,问题就开始了。 / p>

第一个问题:尝试访问servlet应用程序上下文中带有IllegalStateException的带注释的Bean时,抛出了@RefreshScope,以下是stacktrace中有意义的部分:

ERROR: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: No Scope registered for scope name 'refresh'] with root cause
java.lang.IllegalStateException: No Scope registered for scope name 'refresh'

解决方案:通过将 refresh 作用域注册到Servlet应用程序上下文中,可以解决上述错误

@Bean
public CustomScopeConfigurer servletCustomScopeConfigurer(org.springframework.cloud.context.scope.refresh.RefreshScope refreshScope) {
    CustomScopeConfigurer customScopeConfigurer = new CustomScopeConfigurer();
    customScopeConfigurer.addScope("refresh", refreshScope);
    return customScopeConfigurer;
}

问题:假定这种对Web应用程序建模的方法仍然有用(我认为是这样),为什么我找不到任何文档说明必须注册刷新作用域到servlet应用程序上下文,我应该从根应用程序上下文中注册org.springframework.cloud.context.scope.refresh.RefreshScope bean吗?

第二个问题:一旦我在servlet应用程序上下文中注册了刷新作用域,该应用程序就可以正常启动,并且一切似乎都可以正常工作,但是当我尝试更新时来自可刷新bean的一个属性,我得到了混合的结果,当我刷新一个将在根应用程序上下文中修改bean的属性时,我可以看到该bean正在更新,所以一切都很好,但是当我更新一个可以在其中修改bean的属性时在servlet应用程序上下文中,我可以设置要刷新的bean,但是新的属性值未反映在bean中。

解决方案:经过一些测试,我意识到两种情况下的ConfigurableEnvironment是不相同的,在某些时候,父级ConfigurableEnvironment被合并到子级{{1 }}就是在启动时正确初始化servlet上下文中的bean的方式,但是当ConfigurableEnvironment调用ContextRefresher.refresh()时,只有父RefreshEndpoint被更新,子{{1 }}并没有保留旧的值,我现在要做的是在创建Servlet应用程序上下文时注入父级ConfigurableEnvironment,并且一切正常,相关代码:

ConfigurableEnvironment

问题:再次令我感到惊讶的是,缺少有关Spring应用程序声明父和子应用程序上下文的预期行为的文档,也许我只是没有找到它而它确实存在并且令人惊讶。将父ConfigurableEnvironment设置为子servlet上下文的方法正确吗?

默认情况下((父@Bean public DispatcherServlet dispatcherServlet(ConfigurableEnvironment parentEnvironment) { DispatcherServlet dispatcherServlet = new DispatcherServlet(); AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext(); applicationContext.register(WebConfiguration.class); applicationContext.setEnvironment(parentEnvironment); dispatcherServlet.setApplicationContext(applicationContext); dispatcherServlet.setThrowExceptionIfNoHandlerFound(true); return dispatcherServlet; } 未在servlet上下文中设置。)是以下事实:子ConfigurableEnvironment不会被故意刷新或刷新错误?

如果您仍在阅读本文,谢谢!以上问题的答案将不胜感激!

希望这可以帮助其他人解决这些问题。

0 个答案:

没有答案