2017-08-30 2 views
0

J'ai une bibliothèque externe (scala-redis) qui nécessite un ActorSystem implicite lors de l'initialisation du client. Je voudrais avoir mon RedisClient en tant que Singleton dans mon application Play (2.6) parce que cela aurait du sens de l'avoir en Singleton.Dépendance de Guice nécessitant des références à Singleton à l'intérieur AbstractModule

class CustomAppModule(environment: Environment, 
        configuration: Configuration) extends AbstractModule { 
    def configure() = { 
    //val system = getProvider(classOf[ActorSystem]).get() 
    //val system = ActorSystem() 
    //bind(classOf[ActorSystem]).toInstance(system) 

    val redis = RedisClient(configuration.get[String]("redis.host"))(system) 
    bind(classOf[RedisClient]).toInstance(redis)  
    } 
} 

Le premier système échoue en raison de « fournisseur ne peut pas être utilisé jusqu'à ce que l'injecteur a été créé », et le second système échoue parce que cadre de lecture initialise le ActorSystem lui-même lorsque l'application démarre et deuxième système échoue en raison de « la liaison à akka.actor.ActorSystem était déjà configuré sur play.api.inject.BuiltinModule ".

Alors, quelle serait la façon idiomatique avec Guice/DI de procéder dans ce genre de situation? Ai-je besoin d'un wrapper Singleton ayant le RedisClient comme valeur, et où l'ActorSystem peut être injecté?

Répondre

1

Je pense que la méthode fournit résoudra votre problème. Écrivez votre module comme

class MyModule extends AbstractModule { 

    def configure() = { 
    } 

    @Provides 
    @Singleton 
    def givePrecious() : MyClass = { 
     new MyClass() 
    } 
} 

Ici ma classe ressemble

@Singleton 
class MyClass(a: String) { 
    def this() = { 
     this("a") 
     println("constructor called") 
    } 
} 

Maintenant, je tente de créer 3 instances de cette classe

val injector = Guice.createInjector(new MyModule()) 
val precious1 = injector.getInstance(classOf[MyClass]) 
val precious2 = injector.getInstance(classOf[MyClass]) 
val precious3 = injector.getInstance(classOf[MyClass]) 

Vous verrez que la chaîne « constructeur appelée » est imprimé une seule fois. Par souci de simplicité, j'ai fait un comme une chaîne de caractères. vous pouvez essayer d'en faire une instance d'ActorSystem.