【问题标题】:Reloading/Refreshing Spring configuration file without restarting the servlet container在不重启 servlet 容器的情况下重新加载/刷新 Spring 配置文件
【发布时间】:2009-02-10 20:23:03
【问题描述】:

如何在不重新启动 servlet 容器的情况下刷新 Spring 配置文件?

我正在寻找 JRebel 以外的解决方案。

【问题讨论】:

    标签: spring


    【解决方案1】:

    对于那些最近遇到这个问题的人来说——解决这个问题的当前和现代方法是使用Spring Boot's Cloud Config

    只需在可刷新的 bean 上添加 @RefreshScope 注释,在主/配置上添加 @EnableConfigServer

    例如,这个Controller类:

    @RefreshScope
    @RestController
    class MessageRestController {
    
        @Value("${message}")
        private String message;
    
        @RequestMapping("/message")
        String getMessage() {
            return this.message;
        }
    }
    

    当在 Spring Boot Actuator 上调用 refresh(通过 HTTP 端点或 JMX)时,将为 /message 端点返回 message 字符串属性的新值。

    更多实现细节参见官方Spring Guide for Centralized Configuration示例。

    【讨论】:

      【解决方案2】:

      好吧,在测试您的应用时执行这样的上下文重新加载会很有用。

      您可以尝试AbstractRefreshableApplicationContext 类之一的refresh 方法:它不会刷新您之前实例化的bean,但下一次调用上下文将返回刷新的bean。

      import java.io.File;
      import java.io.IOException;
      
      import org.apache.commons.io.FileUtils;
      import org.springframework.context.support.FileSystemXmlApplicationContext;
      
      public class ReloadSpringContext {
      
          final static String header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
              "<!DOCTYPE beans PUBLIC \"-//SPRING//DTD BEAN//EN\"\n" +
              " \t\"http://www.springframework.org/dtd/spring-beans.dtd\">\n";
      
          final static String contextA =
              "<beans><bean id=\"test\" class=\"java.lang.String\">\n" +
                  "\t\t<constructor-arg value=\"fromContextA\"/>\n" +
              "</bean></beans>";
      
          final static String contextB =
              "<beans><bean id=\"test\" class=\"java.lang.String\">\n" +
                  "\t\t<constructor-arg value=\"fromContextB\"/>\n" +
              "</bean></beans>";
      
          public static void main(String[] args) throws IOException {
              //create a single context file
              final File contextFile = File.createTempFile("testSpringContext", ".xml");
      
              //write the first context into it
              FileUtils.writeStringToFile(contextFile, header + contextA);
      
              //create a spring context
              FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(
                  new String[]{contextFile.getPath()}
              );
      
              //echo the bean 'test' on stdout
              System.out.println(context.getBean("test"));
      
              //write the second context into it
              FileUtils.writeStringToFile(contextFile, header + contextB);
      
              //refresh the context
              context.refresh();
      
              //echo the bean 'test' on stdout
              System.out.println(context.getBean("test"));
          }
      
      }
      

      你会得到这个结果

      fromContextA
      fromContextB
      

      实现这一点的另一种方法(也许更简单)是使用 Spring 2.5+ 的 Refreshable Bean 特性 使用动态语言(groovy 等)和 spring,你甚至可以改变你的 bean 行为。看看spring reference for dynamic language

      24.3.1.2。可刷新的豆子

      其中一个(如果不是)最 动态的引人注目的增值 Spring 中的语言支持是 “可刷新豆”功能。

      可刷新的 bean 是 具有动态语言支持的 bean 少量配置,一个 动态语言支持的 bean 可以 监测其底层证券的变化 源文件资源,然后重新加载 本身当动态语言 源文件被更改(例如 当开发者编辑和保存时 对文件的更改 文件系统)。

      【讨论】:

        【解决方案3】:

        我不建议你这样做。 您希望修改配置的单例 bean 会发生什么?您是否希望所有单身人士重新加载?但有些对象可能包含对该单例的引用。

        也可以看到这个帖子Automatic configuration reinitialization in Spring

        【讨论】:

          【解决方案4】:
          猜你喜欢
          • 2010-09-15
          • 1970-01-01
          • 2011-07-10
          • 2017-09-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多