【问题标题】:Good library for parameter injection/properties management用于参数注入/属性管理的好库
【发布时间】:2012-10-10 21:46:03
【问题描述】:

我有一个piece of code,我用它来管理属性已经有一段时间了。我的老板不喜欢这个解决方案,理由是物业管理应该由知名的库来完成,比如 Spring/Guice。这是可以理解的,我正在寻找替代品,但我找不到能够提供我想要的功能的替代品(或者我可能不知道如何正确使用它们)。

我正在寻找的功能是:

  1. 超级容易在编码期间向类添加新属性
    1. 无需触摸构造函数,添加专用字段或设置器
    2. 使用 Java 代码(尽可能)
    3. 易于添加默认值。如果您只想快速配置某些内容并保持代码正常运行,则无需编辑属性文件
  2. 可以使用任何类型(可以在框架内定义从String转换)
  3. 在每个属性的配置加载时运行的自定义验证
    1. 例如检查文件是否存在,检查定义的转换是否成功等。
  4. 能够将参数注入最终字段
  5. 能够自动生成属性文件模板
    1. 特别是定义描述的能力,最好是在 Java 代码中,然后写入模板
  6. 能够在运行时以线程安全的方式更新配置

是否有任何库可以为我提供这些功能?

如果我遗漏了一些东西,而这些都可以通过 Spring/Guice 来满足,那么网上有什么好的资源吗?

Example usage of my solution
Sample of generated property file TEMPLATE (you copy and edit this)

【问题讨论】:

  • 您的功能请求背后是否有可靠的业务需求?通过属性和 DI 进行配置非常标准,只需选择一个 DI 框架即可。
  • @aikox 好吧,我广泛使用所有功能。如果您可以将我引导到可以提供这里大部分功能的 DI 框架,我就在。
  • 我不确定我是否得到了旨在支持的工作流 #5。如果我修改了模板,并想添加其他设置怎么办?那一代是否只打算使用一次?
  • 您希望能够将值注入final 字段,并在运行时更新此配置...为什么?
  • @DNA 我想将一些值注入到最终字段中,而其他值则可以在运行时更新。

标签: java configuration properties dependency-injection configuration-files


【解决方案1】:

无需接触构造函数,添加专用字段或设置器

这不是dependency injection 模式。您可能会替换资源定位器模式,但做得好(特别是在保持可测试性的方式上)并非易事:使用 setter,我可以轻松地重新配置被测类。如果该类依赖于配置文件,每当我需要更改单元测试的设置时,我会编写一个单独的配置文件吗?我会模拟配置类吗?可能,但不完全直截了当...

能够自动生成属性文件模板

正如 cmets 中已经指出的,这似乎不是很有用,因为它不能迁移旧的配置文件。

能够在运行时以线程安全的方式更新配置

这通常需要正在配置的组件的支持(例如,更改线程池大小的设置涉及启动/停止工作线程......)。一般来说,唯一简单的处理方法是重新启动应用程序......

如果您放弃这些要求,Spring 的 PropertyOverrideConfigurer 就非常适合。

或者,如果您在 servlet 容器中运行,您可以在 Spring 配置中添加 JNDI lookups

如果你真的想生成模板,我不知道一个现成的解决方案。我可能会这样做:

class Configuration {

    int threadCount = 10;

    String secretKey;

    @Description("Number of workers. Default value is number of available cores.")
    int workerThreadCount = Runtime.getRuntime().availableProcessors();

    /** Use default settings */
    Configuration() {

    }

    /** read the settings from the file */
    Configuration(Properties props) {
        for (String prop : props) {
            Field f = getClass().getField(prop);
            f.set(this, props.getValue(prop)); 
            // TODO: type conversion, 
            // e.g. with PropertyEditors, 
            // or Spring's ConversionService, 
            // or invoking the constructor that takes a single string argument, 
            // or ...
        }
    }

    void save() {
        for (Field f : getClass().getFields()) {
            // TODO save the setting
        }
    }
}

编写默认配置就像new Configuration().save(file) 一样简单,或者升级现有配置就像`new Configuration(file).save(file)' 一样简单。

与您的方法不同,此方法是静态类型安全的,并且不会使代码使用冗余类型说明符访问配置设置变得混乱。也就是说,而不是

if(config.value(Prop.PROXY_ENABLED,Boolean.class)){

你可以简单地写

if (config.proxyEnabled) {

并且由于该字段可以是布尔类型(不是布尔),因此您甚至不会在此处冒 NullPointerException 的风险。

【讨论】:

  • 感谢您的回答,非常感谢。事实上,我必须为每个测试提供属性文件,我需要不同的配置,而且我不喜欢它不是静态类型安全和冗长的事实。这个解决方案似乎要好得多。谢谢!!!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-09
  • 1970-01-01
  • 2019-09-01
  • 1970-01-01
  • 2022-08-19
  • 2014-05-27
相关资源
最近更新 更多