2015-06-26 10 views
6

Supponiamo che io sono una terza classe parti come segue:Come posso fornire assistenza a una dipendenza non assistita?

public class MyObject { 
    @Inject 
    public MyObject(Foo foo, Bar bar) { ... } 
} 

Supponiamo ora che ho un'interfaccia di fabbrica in questo modo:

public interface MyObjectFactory { 
    public MyObject build(Bar bar); 
} 

L'idea è che vorrei avere un MyObjectFactory che costruisce un MyObject per un valore fisso Foo - ovvero, aggiungendo essenzialmente l'annotazione @Assisted sul parametro del costruttore Bar dall'esterno. Naturalmente, l'implementazione manualmente MyObjectFactory è sempre possibile:

public class MyObjectFactoryImpl implements MyObjectFactory { 
    @Inject private Provider<Foo> foo; 

    @Override 
    public MyObject build(Bar bar) { return new MyObject(foo.get(), bar); } 
} 

ma diciamo che ci sono le condizioni che mi richiedono di avere Guice costruire MyObject casi - per esempio, il metodo intercettori. Questo mi sembra un lavoro per "iniettare l'iniettore":

public class MyObjectFactoryImpl implements MyObjectFactory { 
    @Inject private Injector injector; 

    @Override 
    public MyObject build(Bar bar) { 
     Injector child = injector.createChildInjector(new AbstractModule() { 
      @Override 
      protected void configure() { 
       bind(Bar.class).toInstance(bar); 
       // Set up method interceptors for MyObject here... 
      } 
     }); 
     return child.getInstance(MyObject.class); 
    } 
} 

Questo suona male e caldaia-piatto-y, quindi mi chiedo se ci sono implementazioni alternative e/o un modo per avere Guice generare il fabbrica impl.

risposta

1

Prima di tutto, è raro che si vuole essere passando istanze di MyObject giro nella classe esattamente per le ragioni che descrivi. Non hai il controllo su di essi, quindi non puoi aggiungere annotazioni @Assisted, non puoi aggiungere intercettatori di metodi, ecc. Ecc. Inoltre, cosa succede quando vuoi sostituire la libreria di terze parti per un'implementazione diversa?

Pertanto, è necessario eseguire il wrapping di MyObject in un altro oggetto.

// **Please** choose better names than this in your real code. 
public class MyWrapperBackedByMyObject implements MyWrapperInterface { 
    private final MyObject delegate; 

    @Inject 
    MyWrapperObject(Foo foo, @Assisted Bar bar) { 
     delegate = new MyObject(foo, bar); 
    } 

    @NotOnWeekends // Example of how you might do method interception 
    public void orderPizza() { 
     delegate.orderPizza(); 
    } 
} 

Poi, rimuovere tutti i riferimenti a MyObject in tutto il codice, utilizzando la convenzione di denominazione ho descritto sopra, ci dovrebbe essere solo riferimenti a MyWrapperInterface.

-1

in effetti lo è. Dai un'occhiata Assisted Inject

Includere

 <dependency> 
      <groupId>com.google.inject.extensions</groupId> 
      <artifactId>guice-assistedinject</artifactId> 
      <version>${guice.version}</version> 
     </dependency> 

Aggiornamento iniezione con assistita

public class MyInjectedObject extends MyObject implements MyIntf { 
@Inject 
public MyObject(Foo foo, @Assisted Bar bar) { super(foo,bar); } 
} 

Dovete aggiungere più una sola interfaccia:

public interface MyIntf {} 

Nel modulo legano fabbrica generica al vostro interfaccia

install(new FactoryModuleBuilder() 
      .implement(MyIntf.class, MyInjectedObject.class) 
      .build(MyObjectFactory.class) 
); 

Ora è possibile iniettare MyObjectFactory ovunque si desideri.

MyObject obj = myObjectFactory.build(bar); 
+0

Anche in questo caso, poiché 'MyObject' è di terze parti, non è possibile modificare' MyObject'; altrimenti sarei in grado di usare semplicemente una vecchia iniezione assistita. –

+1

Avvolgilo in un altro oggetto. –

Problemi correlati