繁体   English   中英

在Java中管理应用程序配置属性

[英]Managing application configuration properties in Java

我正在开发需要一些配置文件的Java应用程序,但是我总是忘记了属性名称,并且发现为每个配置属性创建get方法都不方便。 但是,我发现它们对于它们为我提供的返回类型很有用。

我不知道如何在设计良好的Java应用程序中管理配置,但是我想知道如果我使用这样的枚举来进行配置是否是一个好习惯。 我想象如果将本地化文件放在哪里会变得多么复杂。 但是这个想法仍然吸引着我。

public enum Confs {

    HLENGTH("hlength", Integer.class),
    ;

    private String propertyName;
    private Class type;


    private Confs(String propertyName, Class type) {
        this.propertyName = propertyName;
        this.type = type;
    }

    public Object getVal(){
// This hash map is loaded in a singleton class which uses java Properties feature to read the configuration file
        return MyLoadedConfigurationsSingleTon.getMap().get(this.propertyName);
    }

}

无论如何,是否没有解决此问题的标准解决方案?

按键

这确实取决于您的要求。 这里有很多选择。 对于简单的应用程序,我通常使用将任意配置键映射到值的方法。 然后,可以将键的名称指定为字符串常量,例如在某个地方:

public static final String KEY_COLOR = "color";
public static final String KEY_SIZE = "size";

当然,这带来了在哪里指定这些常数的问题。 您可以在一些全局共享的位置(例如,在配置类中,或在某些特殊的常量值类中,甚至像您建议的enum那样)指定它们。 这样的好处是可以让您在一个位置看到所有键名,从而轻松避免冲突。 但是,这具有明显的主要缺点,即破坏模块化并强制所有类都依赖于此键集合-现在添加/删除/移动对象需要您修改全局键集合。

您可以做的另一件事是将配置键名称定义为实际使用它们的类/包中的字符串常量。 这不会破坏模块化。 但是,您现在冒着键名与其他不相关类冲突的风险。 添加新密钥意味着您必须遍历使用配置的每个对象,并确保新密钥名称尚未使用。

但是,传统的Java解决方案是使键名也包括使用它们的类的包(可能还有类名)。 例如:

package com.me.whatever;
public class Something {
    static final String KEY_COLOR = "com.me.whatever.Something.color";
    static final String KEY_SIZE = "com.me.whatever.Something.size";
}

package com.me.util;
public class Other {
    static final String KEY_SIZE = "com.me.util.Other.size";
    static final String KEY_GROUP = "com.me.util.Other.group";
}

有时,仅指定软件包名称更有意义,如果这样可以更好地代表您的情况。

上述想法对于其他配置方案也适用。 例如,使用Preferences API,可以从包名称中得出键的路径。 该API甚至提供了诸如systemNodeForPackage()类的东西来为您处理。

因此,请尽一切可能导致最清晰,最可维护的代码。 在简单性,模块化和灵活性之间找到平衡。 对于简单的一次性应用程序,只要您清楚自己在做什么,就可以打破“ OOP”概念并将它们全部放在一个位置。 否则,请将键值存储在主要使用它们的位置,并利用包和类名来确保唯一性并避免键名空间的污染。

请注意,如果密钥名称在多个包之间分割,则enum不一定是存储密钥名称的最合适或最方便的数据类型。 您当然可以想出一些聪明的系统来完成这项工作,但是通常,字符串常量既足够而且容易使用。 但是,如果您存储的不仅仅是键(例如,值类型),则enum可能是合适的解决方案。


值类型

顺便说一下,对于值类型,那里也有很多选择。 您可以由客户端类完成转换,而不是在配置端强制执行转换-但是,当然,在许多情况下,后者非常方便。

使用enum的问题在于,您实际上是在一个位置定义所有配置键(请参见上文),并且在添加或删除类时很难以模块化的方式扩展可用的配置键集。

您可以创建一个通用配置密钥类,可以根据需要进行实例化,而不是使用固定的enum ,例如:

public class Conf {

    public static class Key {

        final String key; 
        final Class<?> type;

        public Key (String key, Class<?> type) {
            this.key = key;
            this.type = type;
        }

    }

    public Object getValue (Key key) {
        ...
    }

}

通过使用泛型类型,可以轻松地改进上述内容。

然后在您的客户类中:

package com.me.whatever;
public class Something {
    static final Conf.Key KEY_COLOR = new Conf.Key("com.me.whatever.Something.color", Color.class);
    static final Conf.Key KEY_SIZE = new Conf.Key("com.me.whatever.Something.size", Integer.class);
}

再说一次键名:您甚至可以使包名前缀添加成为Conf.Key的函数,类似于Preferences.systemNodeForPackage()工作方式,方法是使声明类的类型作为参数并提取包名,因此,以上声明变为:

static final Conf.Key KEY_COLOR = new Conf.Key(Something.class, "color", Color.class);

结论

我蒙蔽了很多,因为,就像我说的,有无限的选择。 在这里,我无法真正涵盖每种选择的所有情况,但希望您能理解。 与其说是一种理性的方法,还不如说是一种特定的“正确”方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM