我正在Scala中从事多SBT项目。我将核心内容提取到单独的 SBT 项目中。这包括处理配置、第三方库(初始化 RMQ 客户端、初始化 Redis 客户端等(和一些模型。
所以我组织了一些东西,比如在 trait 中加载 config,然后在我需要的地方混合这个特征,只使用Configuration
trait 中定义config
方法,该方法为特定环境加载配置(基于环境变量(。我对数据库做了同样的事情,所以我加载PostgreSQL,打开连接,然后在我需要的地方混合该特征,只使用database
可用于执行查询和其他的方法。
您认为这是好方法吗?优点是我不必在每个项目中处理数据库连接和初始化,而且代码也短得多。但是,关闭连接存在一个问题。在数据库混合的特质中在哪里关闭连接?
感谢有关该主题的任何帮助。谢谢
阿米尔
关于连接,您应该在完成连接时关闭它们(返回到池(,这与混合实现是正交的。
至于配置之类的,我喜欢这种方法,但它的问题在于,大多数时候你希望像加载config
这样的东西是单例的,但如果你只是做一些类似的事情
trait Configuration {
val config = loadConfig
}
class Foo with Configuration
class Bar with Configuration
val f1 = new Foo
val f2 = new Foo
val b1 = new Bar
val b2 = new Bar
然后,您最终将加载配置的四个不同副本。 解决此问题的一种方法是将loadConfig
委托给单一实例对象:
object Configuration {
val config = loadConfig
}
trait Configuration {
def config = Configration.config
}
这有效,但使单元测试和覆盖功能变得更加困难(如果有时我想从数据库加载我的配置怎么办?
另一种可能性是代理类:
trait Configuration {
def loadConfig: Config
lazy val config: Config = loadConfig
}
class ConfigurationProxy(cfg: Configuration) extends Configuration {
def loadConfig = cfg.config
}
object Main extends App with Configuration {
def loadConfig = ??? // executed only one per application
...
}
class Foo extends ConfigurationProxy(Main)
class Bar extends ConfigurationProxy(Main)
val f1 = new Foo
val f2 = new Foo
val b1 = new Bar
val b2 = new Bar
现在,所有四个变量都在查看同一个Config
实例。 但是如果你在某个地方有一个函数需要Configuration
,你仍然可以传递这些中的任何一个:
def connectToDB(cfg: Configuration) = ???
connectToDB(Main)
connectToDB(f1)
connectToDB(b2)
等。