在不重启 servlet 容器的情况下重新加载/刷新 Spring 配置文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/534030/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Reloading/Refreshing Spring configuration file without restarting the servlet container
提问by user64752
How can I refresh Spring configuration file without restarting my servlet container?
如何在不重新启动 servlet 容器的情况下刷新 Spring 配置文件?
I am looking for a solution other than JRebel.
我正在寻找 JRebel 以外的解决方案。
回答by Guillaume
Well, it can be useful to perform such a context reload while testing your app.
好吧,在测试您的应用程序时执行这样的上下文重新加载会很有用。
You can try the refreshmethod of one of the AbstractRefreshableApplicationContextclass: it won't refresh your previously instanciated beans, but next call on the context will return refreshed beans.
您可以尝试refresh其中一个AbstractRefreshableApplicationContext类的方法:它不会刷新您之前实例化的 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"));
}
}
And you get this result
你得到这个结果
fromContextA
fromContextB
Another way to achieve this (and maybe a more simple one) is to use the Refreshable Bean feature of Spring 2.5+ With dynamic language (groovy, etc) and spring you can even change your bean behavior. Have a look to the spring reference for dynamic language:
实现这一点的另一种方法(也许是更简单的方法)是使用 Spring 2.5+ 的 Refreshable Bean 特性,通过动态语言(groovy 等)和 spring,您甚至可以更改 bean 的行为。看看动态语言的spring 参考:
24.3.1.2. Refreshable beans
One of the (if not the) most compelling value adds of the dynamic language support in Spring is the 'refreshable bean' feature.
A refreshable bean is a dynamic-language-backed bean that with a small amount of configuration, a dynamic-language-backed bean can monitor changes in its underlying source file resource, and then reload itself when the dynamic language source file is changed (for example when a developer edits and saves changes to the file on the filesystem).
24.3.1.2. 可提神的豆类
Spring 中动态语言支持的最引人注目的附加值之一(如果不是的话)是“可刷新 bean”特性。
可刷新 bean 是一种动态语言支持的 bean,通过少量的配置,动态语言支持的 bean 可以监视其底层源文件资源的变化,然后在动态语言源文件发生更改时重新加载自己(例如例如,当开发人员编辑并将更改保存到文件系统上的文件时)。
回答by Dovmo
For those stumbling on this more recently -- the current and modern way to solve this problem is to use Spring Boot's Cloud Config.
对于最近在这方面遇到问题的人 - 解决这个问题的当前和现代方法是使用Spring Boot 的 Cloud Config。
Just add the @RefreshScopeannotation on your refreshable beans and @EnableConfigServeron your main/configuration.
只需添加@RefreshScope注释您刷新豆类和@EnableConfigServer你的主/配置。
So, for example, this Controller class:
因此,例如,这个 Controller 类:
@RefreshScope
@RestController
class MessageRestController {
@Value("${message}")
private String message;
@RequestMapping("/message")
String getMessage() {
return this.message;
}
}
Will return the new value of your messageString property for the /messageendpoint when refreshis invoked on Spring Boot Actuator (via HTTP endpoint or JMX).
在 Spring Boot Actuator(通过 HTTP 端点或 JMX)上调用时,将返回端点的messageString 属性的新值。/messagerefresh
See the official Spring Guide for Centralized Configurationexample for more implementation details.
有关更多实现细节,请参阅官方Spring Guide for Centralized Configuration示例。
回答by LiorH
I wouldn't recommend you to do that. What do you expect to happen to singleton beans which their configuration modified? do you expect all singletons to reload? but some objects may hold references to that singletons.
我不建议你这样做。您希望配置修改后的单例 bean 会发生什么?你希望所有的单身人士重新加载吗?但有些对象可能持有对该单例的引用。
See this post as well Automatic configuration reinitialization in Spring
也请参阅这篇文章Spring 中的自动配置重新初始化
回答by Rohan S Raju
You can take a look at this http://www.wuenschenswert.net/wunschdenken/archives/138where once you change any thing in the properties file and save it the beans will be reloaded with the new values.
您可以查看此http://www.wuenschenswert.net/wunschdenken/archives/138,其中一旦您更改了属性文件中的任何内容并将其保存,bean 将使用新值重新加载。

