Как обновить конфигурационный файл Spring без перезагрузки контейнера сервлета?
Я ищу решение, отличное от JRebel.
Как обновить конфигурационный файл Spring без перезагрузки контейнера сервлета?
Я ищу решение, отличное от JRebel.
Ну, может быть полезно выполнить такую перезагрузку контекста при тестировании вашего приложения.
Вы можете попробовать метод refresh
одного из классов AbstractRefreshableApplicationContext
: он не обновит ваш ранее установленный beans, но следующий вызов контекста вернет обновленный beans.
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
Еще один способ достичь этого (и, возможно, более простой) - использовать функцию Refreshable Bean Spring 2.5+ С динамическим языком (groovy и т.д.) И Spring вы даже можете изменить поведение Bean. Посмотрите на ссылку spring для динамического языка:
24.3.1.2. Обновляемый beans
Один из (если не самый) неотразимые добавочные значения динамических поддержка языка в Spring является 'refreshable bean'.
Обновляемый Bean является с поддержкой динамического языка Bean, что с небольшая конфигурация, с поддержкой динамического языка Beanотслеживать изменения в исходный файловый ресурс, а затем перезагрузить когда динамический язык исходный файл изменяется (например, когда разработчик редактирует и сохраняет изменения в файле на Файловая система).
Для тех, кто спотыкается об этом совсем недавно, современный и современный способ решения этой проблемы - использовать Spring Boot Cloud Config.
Просто добавьте @RefreshScope аннотацию к обновляемым компонентам и @EnableConfigServer в свою основную/конфигурацию.
Так, например, этот класс Controller:
@RefreshScope
@RestController
class MessageRestController {
@Value("${message}")
private String message;
@RequestMapping("/message")
String getMessage() {
return this.message;
}
}
Возвращает новое значение вашего свойства message
String для конечной точки /message
, когда refresh
вызывается в Spring Boot Actuator (через конечную точку HTTP или JMX).
См. официальный пример Spring Guide for Centralized Configuration для получения дополнительной информации о реализации.
Я бы не рекомендовал вам это делать. Что вы ожидаете от синглтона beans, который изменила их конфигурация? вы ожидаете перезагрузки всех синглтонов? но некоторые объекты могут содержать ссылки на эти синглтоны.
См. этот пост, а также Автоматическая повторная инициализация конфигурации в Spring
Вы можете посмотреть http://www.wuenschenswert.net/wunschdenken/archives/138, где, как только вы измените какую-либо вещь в файле свойств и сохраните ее, beans будет перезагружать новыми значениями.