2016-07-20 4 views
1

저는 일괄 처리와 같은 play-slick 및 프로그램과 함께 Playframework2.5에서 작업하고 있습니다. 내가 Guice DI 거의 모든 곳에서 데이터베이스 액세스 개체 (DAO)를 포함 사용하고 Scala에서 독립적으로 Playframework Guice를 통해 DI를 수행하는 클래스의 인스턴스를 만듭니다.

/rootPlayProject 
    /app 
    /controllers 
    /filters 
    /services 
    ... 
    Modules 
    /core (sub-project - DAOs,services are placed here) 
    /batch (sub-project depends on core) 

처럼

현재 프로젝트 구조는 다음과 같다. 코어의 인터페이스는 Module에 배치되어 core에 배치되며 루트 프로젝트에서는 Module에 의해 상속됩니다.

코어 모듈 (/rootPlayProject/core/CoreModule.scala)

class CoreModule extends AbstractModule { 
    override def configure() = { 
    bind(classOf[FooDAO]).to(classOf[FooDAOImpl]) 
    .... 
    } 
} 

루트 모듈 (/rootPlayProject/Modules.scala)

이 비록 Playframework 응용 프로그램으로 꽤 잘 작동
class Module extends CoreModule { 
    override def configure() = { 
    super.configure() 
    bind(classOf[FooService]).to(classOf[FooServiceImpl]) 
    } 
} 

, I 배치 모듈 프로그램에 코어 모듈을 사용하고 싶습니다. 플레이 프레임 워크없이 배치를 실행하고 싶습니다.

지금까지 나는이

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

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 기본 모듈과 같은 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()

1

답변은 실제로 플레이 프레임 워크를 DAO에서 분리할지 여부에 달려 있습니다.

옵션 1 :

또는를 분리, :

val application = new GuiceApplicationBuilder() 
    .in(Environment(new File("."), this.getClass.getClassLoader, Mode.Prod)) 
    .build 
Play.start(application) 

옵션 2 :

귀하의 주요 방법을 분리하지 마십시오 단순히 다음 줄은 val injector 라인을 선행 한 수 환경에 특정한 ExecutionContext을 제공 할 수있는 주사 가능한 클래스를 제공 할 수 있습니다. DatabaseConfigProvider을 삽입하려면 더 많은 추상화를 수행하여 Play에 대한 직접적인 종속성을 제거해야합니다. 이 주석은 추상에 대한 Play 관련 구현을 따릅니다. 재생에 대한 종속성이 나에게 충격의 정도로 심각하지 않았다 나는이 시나리오를 발생 내 자신의 프로젝트의 경우


, 나는, 옵션 1을 선택했다.

+0

'Option1'의 경우 내가 원하는 것을하는 동안 재생 응용 프로그램이 실행 중임을 의미합니까? 그렇게하기가 어렵지 않다면, 후자의 것을 선호하므로, exec 애플리케이션을 실행할 필요가 없습니다. – suish

+0

귀하의 경우 옵션 2가 더 합리적 일 수 있습니다. – doctorless

관련 문제