2012-02-11 16 views
28

Ho una fabbrica come sotto,parametro Passo al costruttore con Guice

public final class Application { 

    private static IFoo foo; 

    public static IFoo getFoo(String bar) 
    { 
      // i need to inject bar to the constructor of Foo 
      // obvious i have to do something, not sure what 
     Injector injector = Guice.createInjector(); 
     logger = injector.getInstance(Foo.class); 
     return logger;    
    } 

} 

Questa è la definizione Foo:

class Foo 
{ 
    Foo(String bar) 
    { 

    } 

} 

OK. Non sono sicuro di come passare questo parametro al costruttore di Foo con Guice?

Qualche idea?

risposta

43

Tutte le risposte del "Guice Constructor Parameter" sembrano in qualche modo incomplete. Qui è una soluzione completa, tra cui l'utilizzo:

interface FooInterface{ 
    String getFooName(); 
} 

// Annota il costruttore ei parametri assistiti sulla classe di implementazione

class Foo implements FooInterface { 
    String bar; 

    @Inject 
    Foo(@Assisted String bar) 
    { 
     this.bar = bar; 
    } 

    // return the final name 
    getFooName(){ 
    return this.bar; 
    } 

} 

// Crea un'interfaccia fabbrica con un metodo create() che prende solo i parametri assistiti. // FooFactory interfaccia non ha una classe di implementazione esplicita (Guice Magia)

interface FooFactory{ 
    Foo create(String bar); 
} 

// Assorbire quella fabbrica ad un provider creato da AssistedInject

binderModule implements Module{ 

void configure(Binder binder) { 
    binder.install(new FactoryModuleBuilder() 
     .implement(FooInterface.class, Foo.class) 
     .build(FooFactory.class)); 
} 
} 

// Ora usarlo:

class FooAction{ 

    @Inject private FooFactory fooFactory; 

    doFoo(){ 
     // Send bar details through the Factory, not the "injector" 
     Foo f = fooFactory.create("This foo is named bar. How lovely!"); 
     f.getFooName(); // "This foo is named bar. How lovely!" 
    } 
} 

sacco di aiuti qui: https://google.github.io/guice/api-docs/latest/javadoc/index.html?com/google/inject/assistedinject/FactoryModuleBuilder.html

+0

Non funziona per me. Ho * NullPointerException * perché il costruttore * Foo * non ha mai chiamato. Probabilmente hai bisogno di usare il tuo * Modulo * da qualche parte? –

+0

Fissare il tipo di ritorno mancante del metodo "create" (interfaccia FooFactory). Deve essere: Foo create (Barra delle stringhe); – frhack

1

Se questa classe è una fabbrica, dovrebbe essere un oggetto Guice gestiti, con un metodo di getFoo non statica, e il metodo getFoo sarebbe solo usare

new Foo(bar) 

Non ogni classe deve essere istanziato da Guice .

Vedere anche AssistedInject, per evitare di creare questa fabbrica da soli e lasciare che Guice ne crei uno per voi.

8

Quello che stai probabilmente cercando è utilizzare una fabbrica Guice. Particolarmente facile con la funzionalità AssistedInject, ma hanno un manual example at the top of the page. Il corto di questo per l'esempio manuale è che si ottiene la fabbrica sotto il metodo non statico getFoo che si passa qualsiasi parametro a quello che vi serve e si costruisce l'oggetto da lì.

Questo non funzionerà direttamente se si dispone dell'intercettazione dei metodi in Foo, ma funzionerà in molti altri casi.

Per utilizzare AssistedInject, che per me ha la semantica po 'più pulite e mezzi di cablaggio meno manuale, è necessario l'estensione guice-assistedinject nel classpath, poi, quando la creazione di Foo (beh, FooImpl, dovremmo utilizzare interfacce):

@Inject 
public FooImpl(@Assisted String bar) 
{ 
    this.baz = bar; 
} 

quindi si crea un'interfaccia FooFactory:

public interface FooFactory { 
    public Foo create(String bar); 
} 

Poi, nel vostro modulo Guice:

install(new FactoryModuleBuilder() 
    .implement(Foo.class, FooImpl.class) 
    .build(FooFactory.class)); 

È possibile controllare lo javadoc for FactoryModuleBuilder per esempi con fabbriche più complesse.

+0

sì, fa schifo, è così complicato, la structuremap è molto più flessibile del guice. – DarthVader

+0

Dove posso scaricare StructureMap per Java? – mark

+0

Questo ha funzionato per me, anche se non è molto carina. –

4

so tha questo è vecchio thread ma ho appena raggiunto il problema io stesso oggi. Ho solo bisogno di due o massimo tre diverse istanze di "Foo" e non volevo davvero scrivere tutto il codice bolierplate di Factory. Con un po 'di googling ho trovato questo Stubbisms – Tony’s Weblog Vorrei suggerire questa soluzione che è perfetta se sai esattamente quali istanze hai bisogno.

Nel modulo Guice:

bind(Foo.class).annotatedWith(Names.named("firstFoo")).toProvider(new Provider<Foo>() { 
     @Override 
     public Foo get() { 
      return new FooImpl("topic A"); 
     } 
    }); 
    bind(Foo.class).annotatedWith(Names.named("secondFoo")).toProvider(new Provider<Foo>() { 
     @Override 
     public Foo get() { 
      return new FooImpl("topic B"); 
     } 
    }); 

O in Java 8:

bind(Foo.class).annotatedWith(Names.named("firstFoo")).toProvider(() -> new FooImpl("first")); 
    bind(Foo.class).annotatedWith(Names.named("secondFoo")).toProvider(() -> new FooImpl("second")); 

E nel costruttore del vostro servizio in cui è necessario istanze Foo:

@Inject 
public MyService (
    @Named("firstFoo") Foo firstFoo, 
    @Named("secondFoo") Foo secondFoo) { 
} 

E Foo nel mio case:

public class FooImpl implements Foo { 

    private String name; 

    public FooImpl(String name) { 
     this.name = name; 
    } 

    @Override 
    public String getName() { 
     return name; 
    } 
} 

Spero che aiuti qualcuno.

Problemi correlati