在使用类型安全配置的 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
}
}
有两个问题:
- 有人可能会在 calculate() 在线时重新加载底层配置://做一些事情(一致性)
- 不喜欢在 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
}
}
}
我认为这可以解决您的问题,因为:
- 默认情况下,配置检索是动态的,通过重新加载
- 通过使用一种不求助于可变状态的方法
关于java - 什么是实现类型安全配置重新加载的好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25280040/