【问题标题】:What is the best strategy for loading properties? [closed]加载属性的最佳策略是什么? [关闭]
【发布时间】:2009-08-04 22:34:26
【问题描述】:

我有几个类需要加载一些属性文件,我想知道实现这一点的最佳实践是什么。我想到了两种基本方法:

  • 硬编码每个类中的属性文件名,然后使用Properties 类从FileInputStream 加载,如果有人决定更改属性文件的名称,这可能会出现问题,因为它是硬编码在代码。

    public class A {
        public A() {
            Properties p = new Properties().load(
                    new FileInputStream("properties/Aconfig.properties"));
            String value = p.getProperty("key", "");
        }        
    }
    
  • 创建一个方法,给定一个类名,加载一个与该类同名的属性文件。虽然这种方法不需要硬编码属性文件名,但它确实要求我们在命名文件时遵循一些约定,这可能会导致混淆。

    public class A {
        public A() {
            Properties p = PropertiesHelper.loadFromClassName(A.class.getName());
            // here, we **assume** that there is a A.properties file in the classpath.
        }
    }
    

但是,可能还有许多其他更优雅的方法,这就是我提出这些问题的原因:i) 在 Java 中加载属性文件的最佳实践是什么? ii)您是否使用任何负责这项工作的助手类? iii) 您通常在哪里(在代码中)加载属性文件?

另外,一个类可以“自动加载”它的属性吗?或者我应该将我需要的参数传递给构造函数?传递参数的问题是,对于某些类来说太多了(大约 20 个,代表统计模型中的参数)。

【问题讨论】:

    标签: java properties


    【解决方案1】:

    最佳做法是使用某种dependency injection 容器 - 例如Spring FrameworkGoogle Guice

    它解决了各种问题——你不必将你的类绑定到特定的属性文件名,你不必担心在该类中加载所述属性并处理可能的异常,而且你不必通过30 个属性文件名作为命令行参数(或系统属性)。

    除了属性加载之外,它还有助于处理许多其他事情 :-) - 试试吧,你会想知道如果没有它,你是如何生活的。

    更新:顺便说一句,your other question 也是 Spring 会处理的事情之一。

    更新 #2: 我刚刚意识到我已经 already tried to push Spring 在你身上了 :-) 冒着重蹈覆辙的风险,Spring 在这里确实有助于抽象。根据您在属性文件中存储的内容,您可能根本不需要它们(如果它们处理配置),或者您将获得一个非常好的 API 来处理它们(如果它们是资源包或类似的东西)。

    【讨论】:

    • 是的 : ),我正在考虑使用 SF 来解决该特定问题。但是,为此,我希望每个人(不一定是计算机程序员)都可以轻松配置/更改属性文件,因此需要一个简单的基于“key=value”的文件模式。
    • 你仍然可以做到这一点。 Spring 有一个非常好的资源抽象层:static.springsource.org/spring/docs/2.5.x/reference/…,它可以让您“按原样”处理这些属性文件,而无需将您的类直接绑定到它们。
    • 嗯,我要去读一下,谢谢。我以为您指的是 中的 元素。至于您的问题,我基本上在其中存储了许多模型参数(例如,numberOfTrials=50 等 [数值])。
    • <property> 元素是您放置属性文件名的位置;然后在您的班级中,您将有一个以 Resource 作为参数的相应设置器。就模型参数而言,这些参数可能适合也可能不适合通过<property> 进行设置——这取决于它们是否具有合理的“默认值”或者用户必须指定的东西。您可能需要查看 PropertyPlaceholderConfigurer 或 PropertyOverrideConfigurer:static.springsource.org/spring/docs/2.5.x/reference/beans.html,它们充当属性文件和通过上下文设置的 <property> 之间的桥梁
    【解决方案2】:

    为属性文件提供多个位置并将它们(一个接一个)加载到单个 Properties 对象中。此方案允许映射具有默认值,然后可以在多个点上覆盖该默认值。

    【讨论】:

      【解决方案3】:

      文件名可以很容易地在应用程序的命令行中传递。这可以作为arg to the main method(在主类名之后)或作为属性(我相信像 aperkins 所暗示的那样)使用-D flag 来完成。

      【讨论】:

      • 我知道这一点,但我的应用程序也需要在 Web 环境中工作。另外,我有很多要传递的文件名,每次使用该方法创建一个新脚本时,我都需要更改我的 run.sh(或类似)脚本。
      • 如果您对文件名进行硬编码,您的处境也类似。您可以在命令行上有一个文件名,其中包含您需要的配置文件列表。
      【解决方案4】:

      过去,我通过系统属性加载了属性——文件名是通过系统属性传入的,然后我加载了那个文件。如果未设置系统属性,我们将使用默认名称。如果该文件不存在,那么您需要决定在那里做什么。

      这样做的好处是有一个标准,但他们可以使用命令行参数覆盖它的位置/名称。

      只是我的 2 美分。

      【讨论】:

        【解决方案5】:

        我建议避免使用文件和文件系统相关的路径。通常最好使用类路径路径(嗯,没有双关语......),因为: - 它通过在运行时和测试时间之间分离类加载器来使您的代码可测试,这是任何体面的构建系统通常会完成的事情 - 它使您的代码位置独立并允许您忽略操作系统问题 - 它使您的代码与独立应用程序或在容器内(轻量级、servlet、应用程序服务器等)一样工作。

        您可以查看 PropertyResourceBundle,它具有可识别区域设置的不错的附加功能,因此您可以使用不同的区域设置定义不同的属性。请注意,可以滥用 Locale 来提供独立于 l10n 或 i18n 问题的参数化,例如。我在一个项目中使用了“windows”和“linux”语言环境,因为您可以构建自己的 Locale 实例并将其传递给加载程序。

        或者你可以自己构建路径...

        或者您可以从输入流中加载您的属性:

              Properties prop = Properties.load(getClass().getResourceAsStream("/myprops"));
        

        HTH。

        【讨论】:

        • Spring 很不错,但对于这样一个简单的功能来说可能有点矫枉过正。你可以看看 PicoContainer,就 DI 而言,它比 Spring 更轻量级
        • 我可能忽略了你的问题,给你一个不充分的答案。在您的特定情况下,我已经做的是托管要加载到根属性文件中的属性。无论如何,这些信息必须存储在某个地方:硬编码在您的代码中,或者在配置文件中。更好地对所有内容使用相同的机制......但是,如果您的属性与类的名称相关联,那么您最好使用第二种解决方案,但存储您的属性以便在主源代码树之外轻松编辑并将它们添加到运行时的类路径。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-10-25
        • 1970-01-01
        • 2016-11-27
        • 1970-01-01
        • 2021-11-20
        • 1970-01-01
        • 2015-07-31
        相关资源
        最近更新 更多