【问题标题】:Spring override properties at runtime and keep them persistentSpring 在运行时覆盖属性并保持它们的持久性
【发布时间】:2014-05-06 10:03:37
【问题描述】:

我正在使用 Spring 3.2.8 并将我的设置保存在属性文件中。现在我希望其中一些在运行时覆盖。​​我想通过覆盖属性文件中的旧值来保持新值的持久性。

如何在 Spring 中做到这一点?一些属性我用@ Value注入,而另一些用MessageSource.getMessage(String, Object [], Locale)注入。 bean 已经用这些值实例化了​​。如何访问属性、存储它们并更新系统范围内的所有 bean?

谢谢!

【问题讨论】:

  • 属性是如何被覆盖的以及它们多久改变一次?
  • 属性实际上没有被覆盖。我必须实现这一点。在我看来,这样一个简单功能的实现在 Spring 中是非常复杂的。现在我想有一个带有覆盖值的附加文件,并在 Spring 属性中保留默认值。我尝试使用我自己的ConfigurationBean 并将其注入我需要属性值的地方。所以我有更好的控制力。
  • 我想我现在明白你的问题了。属性的值在 /settings 页面上设置。不是那么频繁,但是服务器无法重启。
  • 它是属性和bean之间的一对一映射还是多个bean使用的单个属性?那么如果一个属性发生变化,是否有多个位置需要更新?
  • 肯定多个 bean 使用了一个属性。没有人希望手动更新所有 bean :)。

标签: java spring spring-mvc


【解决方案1】:

好的,鉴于你的后续回答,我会保持这个相当简单,并使用你已经知道的 Spring。我会做一些假设,注解配置对你来说是可以的。

在我的示例中,我假设您要配置的所有属性都与称为 ServerConfiguration 的东西相关,并且最初这些属性是从类路径上的 server.properties 读取的。

所以在第 1 部分,我将定义一个名为 ServerProperties 的 bean,其中注入了来自 server.properties 的原始值。

所以:

@Component
public class ServerProperties
{
     @Value("${server.ip}");
     private String ipAddress;

     ...

     public void setIpAddress(String ipAddress)
     {
        this.ipAddress = ipAddress;
     }

     public String getIpAddress()
     {
        return this.ipAddress;
     }

}

其次,在任何依赖这些属性的地方,我都会注入ServerProperties 的实例,而不是使用@Value,例如:

@Component
public class ConfigureMe
{
    @AutoWired
    private ServerProperties serverProperties;

    @PostConstruct
    public void init()
    {
        if(serverProperties.getIpAddress().equals("localhost")
        {
            ...
        }
        else
        {
            ...
        }
    }
}

第三,我将公开一个简单的ControllerServerProperties 被注入其中,以便您可以使用您的网页来更新系统属性,例如:

@Controller
public class UpdateProperties
{

    @AutoWired
    private ServerProperties serverProperties;        

    @RequestMapping("/updateProperties")
    public String updateProperties()
    {
       serverProperties.setIpAddress(...);
       return "done";
}

最后,当 ApplicationContext 关闭时,我将在 ServerProperties 上使用 @PreDestroy 将当前属性值刷新到文件中,例如:

@Component
public class ServerProperties
{

    @PreDestroy
    public void close()
    {
        ...Open file and write properties to server.properties.
    }
}

这应该为您提供所需的框架。我确信它可以被调整,但它会让你到达那里。

【讨论】:

  • 这正是我在此期间所做的。只有我没有实现的是@PreDestroy 注释方法。我仍然需要考虑立即存储属性是否更好,因为 JVM 可能会被 KILL 信号或类似的东西触发,因此没有时间执行 @PreDestroy 方法。注释基本上没问题,但我在 setter 上使用它,而不是直接在变量上使用。我喜欢有一个关于我的字段的 setter / getter 布局。
  • 谢谢,我觉得这个解决方案很简单而且足够好。有趣的是 Spring 不提供开箱即用的属性处理。
  • Apache Commons 配置看起来很有趣。也许我可以在不重新发明轮子的情况下使用它。
  • Spring Boot 确实引入了类似的东西 (docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/…),但它绝对不是主要 Spring 代码库的一部分。
猜你喜欢
  • 2018-02-07
  • 1970-01-01
  • 2015-03-11
  • 1970-01-01
  • 2012-02-18
  • 1970-01-01
  • 2021-09-23
  • 2016-06-11
  • 1970-01-01
相关资源
最近更新 更多