2014-03-02 63 views
3

我目前正在探索在Play2.2应用程序中使用Scaldi进行依赖注入。Scaldi依赖注入和Akka Actor

我已阅读Scaldi网站上的文档,但我不清楚的是如何将它与Akka一起使用。

我至今在我的项目:

Models/ (Daos and case classes) 
    User.scala 
Services/ (Akka Actors) 
    UserService.scala 
    ProfileService.scala 
Managers/ (Regular Manager Classes) 
    UserManager.scala (The Trait Interface) 
    UserManagerImpl.scala (An actual implementation) 
    UserManagerMock.scala (Mocked version) 
    etc.. 

在UserService.scala我会使用的UserManager的实例做的工作:

class UserService extends ServiceActor with Injection 
{ 
    val userManager = inject[UserManager] 

    def receive = { 
     case Register(email: String, password: String) 
    } 
} 

object UserService extends Service 
{ 
    case class Register(email: String, password: String) 

    override protected val actorRef = Akka.system.actorOf(Props[UserService].withRouter(SmallestMailboxRouter(resizer = Some(resizer)))) 
} 

然后取决于注入经理,如果将所有的工作委托给经理,这位演员可以被嘲笑吗?

但是,如果经理需要调用其他服务,它们只是伴侣对象呢?或调用其他服务的服务也是通过随播对象引用的?

有没有人有一些关于如何将Akka与Scaldi整合的指针?

回答

4

您提到过,您正在使用伙伴object作为服务。我还注意到,你是 创建object s内的演员。总的来说,我会阻止你这样做。斯卡拉(同伴)object s 只是单身人士。虽然它们在某些情况下可能是有用和适当的,但通常它们被认为是反模式而不是模式,特别是如果您想在您的应用程序中执行依赖注入或控制反转。这有很多原因,但在这种情况下最重要的是:很难嘲笑它们,很难控制它们的实例化,并且通常它们代表了控制反转的反面。

另一个问题是您正在创建这些单例对象内部的actor。演员模特的非常重要的方面是 supervision hierarchy。通过单独创建这个演员 (UserService在你的情况下),你最有可能让监护人演员成为主管,在大多数情况下, 不是你想要的。所以我会建议在另一个演员中创建大多数演员,除了少数需要成为顶级演员的 。这将确保他们有适当的监督等级。

如果您使用Scaldi,这些想法也保持不变。 scaldi-akka提供了 方便的方式为某个特定演员注入ActorRefProps。这里是你怎么能 注入正常的绑定和ActorRefs一个小例子:

class ProfileManager (implicit inj: Injector) extends Injectable 

trait UserManager { 
    def register(email: String, password: String): User 
} 

class UserManagerImpl(implicit inj: Injector) extends UserManager with Injectable { 
    val profileManager = inject [ProfileManager] 

    def register(email: String, password: String) = ??? 
} 

class UserService(implicit inj: Injector) extends Actor with AkkaInjectable { 
    val userManager = inject [UserManager] 

    import UserService._ 

    def receive = { 
    case Register(email, password) => 
     userManager 
    } 
} 

object UserService { 
    case class Register(email: String, password: String) 
} 

class ReceptionistService(implicit inj: Injector) extends Actor with AkkaInjectable { 
    val userManager = injectActorRef [UserService] 
    def receive = ??? 
} 

请注意,injectActorRef创建和电流演员的上下文中的演员。所以相当于将 是:

val userManager = context.actorOf(injectActorProps[UserService]) 

现在,您需要创建为ActorSystem(这是可选的,如果你使用的播放,你可能 需要从播放应用,已经有一个得到ActorSystem结合),服务(这是你的情况演员) 和管理者:

implicit val module = new Module { 
    bind [ActorSystem] to ActorSystem("MySystem") 

    binding toProvider new UserService 
    binding toProvider new ReceptionistService 

    bind [UserManager] to new UserManagerImpl 
    binding to new ProfileManager 
} 

toProvider结合Actor的IT是非常重要的。这可以确保,每次Akka要求Scaldi提供某些 特定的Actor时,它总会得到它的新实例。现在

,如果你想ReceptionistService是你的顶级演员,你可以使用它像这样:

implicit val system = inject [ActorSystem] 

val receptionist = injectActorRef [ReceptionistService] 

receptionist ! DoStuff 

在这种情况下,system监护人的演员将是它的主管。