我正在开发Playframework2.5,其中包括游戏和与之相关的程序,如批处理。
当前的项目结构就像
/rootPlayProject
/app
/controllers
/filters
/services
...
Modules
/core (sub-project - DAOs,services are placed here)
/batch (sub-project depends on core)
我几乎到处都使用Guice DI包括数据库访问对象(DAO)。
核心中的接口绑定在放置在Module
中的core
中,最终会被根项目中的Module
继承。
核心模块(/rootPlayProject/core/CoreModule.scala)
class CoreModule extends AbstractModule {
override def configure() = {
bind(classOf[FooDAO]).to(classOf[FooDAOImpl])
....
}
}
根模块(/rootPlayProject/Modules.scala)
class Module extends CoreModule {
override def configure() = {
super.configure()
bind(classOf[FooService]).to(classOf[FooServiceImpl])
}
}
这可以很好地用作Playframework应用程序,我想将核心模块用于批处理程序,我想在没有playframework的情况下运行批处理。
到目前为止,我尝试过这样的事情
object BatchA {
def main(args: Array[String]) = {
val injector = Guice.createInjector(new CoreModule)
val foo = injector.getInstance(classOf[FooDAO])
//do something with foo.
}
}
但由于我的DAO要求Playframework创建诸如ExecutionContext
,play.api.db.slick.DatabaseConfigProvider
和@play.db.NamedDatabase
之类的内容,因此以上代码无法运行。
我的问题是,如果没有播放应用程序构建器,我怎么能让这些东西受到约束?
提前致谢。
答案 0 :(得分:1)
答案取决于您是否想要将Play Framework与DAO实际分离。
选项1:不要解耦
您的主要方法可能只是在val injector
行之前有以下几行:
val application = new GuiceApplicationBuilder()
.in(Environment(new File("."), this.getClass.getClassLoader, Mode.Prod))
.build
Play.start(application)
选项2:解耦
或者,您可以提供可注入的类,它们可以提供特定于环境的ExecutionContext
。如果要注入DatabaseConfigProvider
,则必须执行进一步的抽象以消除对Play的直接依赖。注释将遵循抽象的Play特定实现。
对于我遇到这种情况的我自己的项目,我选择了选项1,因为对Play的依赖程度对我来说影响不够严重。
答案 1 :(得分:0)
GuiceInjectorBuilder
可以做到这一点。
trait PlayInjector {
lazy val injector = new GuiceInjectorBuilder().configure(Configuration.load(Environment.simple(mode = Mode.Dev)))
.bindings(new BuiltinModule, new CoreModule, new SlickModule).disable(classOf[Application]).injector
def closeInjector = injector.instanceOf[DefaultApplicationLifecycle].stop
}
BuiltinModule绑定Play基本模块,例如ExecutionContext
,ExecutionContextExecutor
或ActorSystem
。
您可以使用BuiltinModule
使自己的模块仅绑定您需要的内容,并禁用您不需要的类更简单。
如何使用
object Foo extends PlayInjector {
def main(args: Array[String]) = {
val foo = injector.instanceOf[FooDAO]
val bar = injector.instanceOf[BarDAO]
//do something
//when you finish things you want to do
closeInjector
}
}
由于某些模块(如PlaySlick)使用ApplicationLifecycle.addStopHook
来处理关闭操作。执行它们更安全,而不是只调用sys.exit()