2014-03-02 67 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監護人的演員將是它的主管。