2010-08-04 3 views
10

J'ai une classe comme si, que je me crée quelque part dans mon code:Guice Injecter terrain en classe n'a pas été créé par Guice

class StarryEyes { 
    @Inject MyValidator validator; 

    public StarryEyes(String name) { 
     //.. 
    } 

    public doSomething() { 
     // validator is NULL 
    } 
} 

Je veux Guice injecter une instance de validateur, qui a une @Singleton annotation. J'ai un module qui est chargé au démarrage et il contient la ligne:

bind(MyValidator.class); 

Cependant, il ne semble pas fonctionner comme « validateur » est toujours nulle. J'ai essayé un certain nombre de variations comme:

bind(MyValidator.class)toInstance(new MyValidator()); 

ou d'autres choses comme ça. Est-ce que ce n'est pas comme ça que Guice est censé travailler?

Répondre

33

Généralement, Guice doit créer des objets pour les injecter. Si vous appelez simplement new StarryEyes(name), Guice ne verra jamais cet objet et ne pourra donc pas l'injecter. Une chose que vous pouvez faire est d'appeler injector.injectMembers(obj) sur l'objet après l'avoir créé. Je ne recommanderais pas cela, cependant, car vous devriez éviter de faire référence à l'injecteur dans votre code.

Ce que vous voulez probablement ici est Assisted Inject. Avec Assistée Injecter, vous souhaitez déclarer le constructeur pour quelque chose de votre classe comme ceci:

@Inject public StarryEyes(MyValidator validator, @Assisted String name) 

Ce que cela signifie est que validator est un paramètre qui Guice devrait injecter, alors que name doit être « Assisté » (qui est, à condition au moment où l'instance est créée).

Vous créez ensuite une interface comme ceci:

public interface StarryEyesFactory { 
    StarryEyes create(String name); 
} 

Avec Injecter assistée, Guice peut alors mettre en œuvre cette usine pour vous. Vous liez comme ceci:

bind(StarryEyesFactory.class).toProvider(
    FactoryProvider.newFactory(StarryEyesFactory.class, StarryEyes.class)); 

Vous Injecter ensuite un StarryEyesFactory partout où vous voulez créer une instance de celui-ci. Si vous aviez précédemment appelé new StarryEyes(name), vous appelez maintenant starryEyesFactory.create(name) à la place. Lorsque vous appelez le create(name) en usine, il prend le nom et le transmet au constructeur et fournit le validateur lié lui-même.

À partir de Guice 3, vous le faites en utilisant un FactoryModuleBuilder:

install(new FactoryModuleBuilder().build(StarryEyesFactory.class));