java - 什么是实现类型安全配置重新加载的好方法

标签 java scala concurrentmodification typesafe-config

在使用类型安全配置的 Scala 应用程序中,我想添加在运行时重新加载配置的可能性。 Config 实例是不可变的。这是我目前所拥有的:

package config

trait Settings {
  private[config] var config: Config = ConfigFactory.empty()
  def engine: EngineSettings
}

trait EngineSettings {
  def weight: Int
  def offset: Int
}

class AppSettings {
  override def engine = new EngineSettings {
    override def weight = config.getInt("engine.weight")
    override def offset = config.getInt("engine.offset")
  }
}

object Settings {
  private val namedSettings = new TrieMap[String, AppSettings]
  def load(configName: String = "local"): Settings = {
    // load config
    // create or update AppSettings
    // add to map and return
  }
}

最初使用 Settings.load 创建一个 Settings 实例。该实例引用被传递给其他类。然后第二个线程可以通过再次调用 Settings.load 来重新加载底层配置。以下是您如何访问它:

class Engine(settings: Settings) {
  def calculate() = {
    val weight = settings.engine.weight
    // do some stuff
    val offset = settings.engine.offset
  }
}

有两个问题:

  1. 有人可能会在 calculate() 在线时重新加载底层配置://做一些事情(一致性)
  2. 不喜欢在 Settings trait 中使用 var

我怎样才能改进这个设计:)

最佳答案

您可以将 config 转换为支持配置缓存失效(并具有合理的默认值)的方法,这样您就可以在动态(以下示例中的默认值)和性能之间进行选择。

一般来说,我建议您使用 TypeSafe Config 的良好 Scala 类型安全包装器,例如 Ficus(例如 Gradle-stype artifact dependency net.ceedubs:ficus_2.11:1.1.1)

package config

import scala.collection.concurrent.TrieMap

import com.typesafe.config.{Config, ConfigFactory}
import net.ceedubs.ficus.Ficus._

trait Settings {
  protected[config] def config (
    name: String = "local",
    invalidateCache: Boolean = false
  ): Config = {
    if (invalidateCache) { ConfigFactory invalidateCaches }
    ConfigFactory load name
  }
  def engine: EngineSettings
}

trait EngineSettings {
  def weight: Int
  def offset: Int
}

class AppSettings(val name: String = "local") extends Settings {
  val c = config()

  override def engine = new EngineSettings {
    override def weight = c.as[Int]("engine.weight")
    override def offset = c.as[Int]("engine.offset")
  }
}

object Settings {
  private val namedSettings = new TrieMap[String, AppSettings]
  def load(configName: String = "local"): Settings = {
    // e.g.
    val loadedUpToDate = new AppSettings
    namedSettings +=
      ((configName + "." + System.currentTimeMillis, loadedUpToDate))
    new Settings {
      override def engine = loadedUpToDate.engine
    }
  }
}

我认为这可以解决您的问题,因为:

  1. 默认情况下,配置检索是动态的,通过重新加载
  2. 通过使用一种不求助于可变状态的方法

关于java - 什么是实现类型安全配置重新加载的好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25280040/

相关文章:

ArrayList处理中的java.util.ConcurrentModificationException

javascript - 在 Java 中获取选项文本值

java - 跨平台桌面开发

java - 加载上下文后,Spring java config 启动 @Async 方法

scala - 在Scala中计算素数: how does this code work?

string - Scala:删除最后一次出现的字符

Java如何在循环时添加到数组列表

java - 强制执行打印顺序,但线程在一次迭代后彼此等待

scala - 如何将DataFrame直接保存到Hive中?

java - 在迭代中从 HashSet 中删除元素