2015-06-26 2 views
6

nehme ich an einen Dritten Klasse wie folgt:Wie kann ich eine nicht unterstützte Abhängigkeit unterstützen?

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

Nehmen wir nun an, dass ich eine Fabrik Schnittstelle wie so haben:

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

Die Idee ist, dass ich eine MyObjectFactory haben wollen, dass eine baut MyObject für eine feste Foo - das heißt, im Wesentlichen die @Assisted Annotation auf dem Bar Konstruktor Parameter von außen hinzufügen. Natürlich manuell MyObjectFactory Umsetzung ist immer möglich:

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

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

Aber lassen Sie uns sagen, dass es Bedingungen gibt, die mich erfordern MyObject Instanzen Guice bauen haben - zum Beispiel Verfahren Abfangjäger. Dies scheint wie ein Job für „Einspritzen des Injektors“:

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); 
    } 
} 

Das klingt böse und Kessel-Platte-y, so frage ich mich, ob es irgendwelche alternative Implementierungen und/oder eine Möglichkeit zu haben, Guice die Erzeugung Fabrikimpl.

Antwort

1

Zunächst einmal ist es selten, dass man für das Bestehen Instanzen von MyObject um in der Klasse sein wollen genau die Gründe, die Sie beschreiben. Sie haben keine Kontrolle über sie, Sie können also keine @Assisted Annotationen hinzufügen, Sie können keine Methoden-Interzeptoren hinzufügen usw. usw. Und was passiert, wenn Sie die Third-Party-Bibliothek für eine andere Implementierung austauschen wollen?

Daher sollten Sie MyObject in ein anderes Objekt wickeln.

// **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(); 
    } 
} 

Dann entfernen Sie alle Verweise auf MyObject im gesamten Code, der Namenskonvention ich oben beschrieben, gibt es nur Hinweise auf MyWrapperInterface sein sollte.

-1

eigentlich ist es. Werfen Sie einen Blick Assisted Inject

Fügen

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

Update-Injektion mit unterstützt

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

Sie haben eine weitere Schnittstelle hinzuzufügen:

public interface MyIntf {} 

In Ihrem Modul binden generische Fabrik zu Ihrem Schnittstelle

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

Jetzt können Sie MyObjectFactory injizieren wo immer Sie wollen.

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

Da 'MyObject' ein Drittanbieter ist, kann ich' MyObject' nicht ändern; Sonst wäre ich in der Lage, einfach die alte assistierte Injektion zu verwenden. –

+1

Wickeln Sie es in ein anderes Objekt. –

Verwandte Themen