如何使用 Spring 重新加载属性?

Posted

技术标签:

【中文标题】如何使用 Spring 重新加载属性?【英文标题】:How to reload properties with Spring? 【发布时间】:2012-10-26 05:32:24 【问题描述】:

我在 Spring 3 中使用属性文件。 当 Spring 初始化其上下文时,它会加载属性文件并将其放入带有 @Value 注释的所有 bean 中。

我希望有可能更新文件中的某些属性,并在服务器上公开一个 JMX,它将新属性重新加载到 Spring - 无需重新启动服务器并重新加载其上下文。

我可以通过使用一些 Spring 方法 重新加载属性并将它们填充到所有 bean 来实现这一点,还是我应该自己编写类似的东西?

【问题讨论】:

【参考方案1】:

我建议将java.util.Properties 替换为Apache Commons Configuration 项目中的PropertiesConfiguration。它支持自动重新加载,无论是通过检测文件何时更改,还是通过 JMX 触发。

【讨论】:

这没问题,但我怎样才能将所有新属性填充到 bean 中?我想使用一些 spring 方法来重新加载这些属性并检查所有 bean 并设置新值 假设 PropertiesConfiguration 是你的 bean 的一个属性,没有什么需要重新填充,实例会自行更新。 您应该查看 owner.aeonbits.org 而不是 PropertiesConfiguration。【参考方案2】:

我认为没有通用的方法可以做到这一点。最“干净”的方法是关闭 Spring 上下文并从头开始构建它。例如,考虑使用 DBCP 连接池并更新它的数据库连接 URL。这意味着必须正确关闭池,然后必须创建新对象,然后还必须更新对池的所有引用。现在,一些 bean 可能会从该池中获取连接,并且更新池配置意味着您需要以某种方式重新请求连接。因此,bean 可能需要知道如何做到这一点,这并不常见。

我建议使用配置和更新事件创建单独的 bean,并将该 bean 作为您需要了解配置更改的所有 bean 的依赖项。然后,您可以使用 Apache Commons Configuration 来监视文件更改并传播配置更新。

也许使用 JMS 很好(如果您以后要分发您的应用程序)。

【讨论】:

你的回答给了我足够的洞察力来回答类似的问题***.com/a/52648630/39998How to hot reload properties in Java EE and Spring Boot。谢谢!【参考方案3】:

是的,您可以使用 Spring JMX 方式执行此操作。将这些 bean 添加到您的 spring 配置文件中。创建一个单独的方法来读取属性文件。在此示例中,我使用 callThisAgain() 方法。

<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
    <property name="beans">
        <map>
            <entry key="your.package.bean:name=sampleBeanService" value-ref="sampleService"/>
        </map>
    </property>
    <property name="assembler">
        <bean class="org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler">
            <property name="managedMethods">
                <value>
                    callThisAgain <!--Simply declare the method name here (only the name) -->
                </value>
            </property>
        </bean>
    </property>
</bean>

<bean class="org.springframework.jmx.support.ConnectorServerFactoryBean" depends-on="rmiRegistry">
    <property name="objectName" value="connector:name=rmi"/>
    <property name="serviceUrl" value="service:jmx:rmi://127.0.0.1/jndi/rmi://127.0.0.1:11000/sample"/>
</bean>

<bean id="rmiRegistry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">
    <property name="port" value="11000"/>
</bean>

之后,您可以使用 jconsole 重新加载您的方法,而无需重新启动服务器。

【讨论】:

【参考方案4】:

使用spring常用的apache如下:

@Component
public class ApplicationProperties 
    private PropertiesConfiguration configuration;

    @PostConstruct
    private void init() 
        try 
            String filePath = "/opt/files/myproperties.properties";
            System.out.println("Loading the properties file: " + filePath);
            configuration = new PropertiesConfiguration(filePath);

            //Create new FileChangedReloadingStrategy to reload the properties file based on the given time interval
            FileChangedReloadingStrategy fileChangedReloadingStrategy = new FileChangedReloadingStrategy();
           fileChangedReloadingStrategy.setRefreshDelay(60*1000);
            configuration.setReloadingStrategy(fileChangedReloadingStrategy);
         catch (ConfigurationException e) 
            e.printStackTrace();
        
    

    public String getProperty(String key) 
        return (String) configuration.getProperty(key);
    

    public void setProperty(String key, Object value) 
        configuration.setProperty(key, value);
    

    public void save() 
        try 
            configuration.save();
         catch (ConfigurationException e) 
            e.printStackTrace();
        
    

【讨论】:

【参考方案5】:

Apache 为我们提供了使用可重新加载属性文件的实用程序。

<bean id="propertiesReloadingStrategy" class="org.apache.commons.configuration.reloading.FileChangedReloadingStrategy">
    <property name="refreshDelay" value="30000" /> <!-- 30 seconds -->
</bean>

<bean id="reloadableProperties" class="org.apache.commons.configuration.PropertiesConfiguration">
    <constructor-arg value="file:/web/$weblogic.Domain/$weblogic.Name/$app.Name/reloadable_cfg/Reloadable.properties"/>
    <property name="reloadingStrategy" ref="propertiesReloadingStrategy"/>
</bean>

【讨论】:

【参考方案6】:

虽然这里有些人建议使用外部方式来使用属性(Spring 自己使用属性文件的方式之外)。这个答案正是您在 Spring Boot 和 Java EE 中寻找的 https://***.com/a/52648630/39998 Hot Reloading 属性。

【讨论】:

以上是关于如何使用 Spring 重新加载属性?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 IDEA Intellij 上使用 Spring-boot 进行自动重新加载

如何让是spring启动时加载一个类。这里类实现了读取xml配置数据到内存中(不是属性文件)

关闭或停止后重新加载弹簧上下文

如何在 Angular、spring-boot、maven 项目中配置项目以自动重新加载浏览器

使用spring boot loader WarLauncher时如何在war文件之外加载属性文件?

如何配置 Spring bean 容器来加载 Java 属性文件?