2016-03-29 6 views
0

ich bin Guice Verwendung aus einer Konfigurationsdatei, eine Klasse mit einigen Argumenten zu initialisierenGuice FactoryModuleBuilder eine Instanz mit Konstruktorparameter

@Provides 
@Singleton 
RetryServiceCaller provideMaxRetryAttempts(@Named("config") JsonObject config) throws IOException { 
    JsonObject retryDetails = config.getJsonObject("retry_details"); 
    return new RetryServiceCaller(retryDetails.getInteger("maxRetryAttempts"), retryDetails.getInteger("upperBoundary"), retryDetails.getInteger("lowerBoundary"), 
            retryDetails.getLong("multiplicationFactor"), retryDetails.getInteger("timeout"), retryDetails.getInteger("increaseTimeout")); 
} 

Diese Klasse in eine andere Klasse eingespritzt wird, die Singletons als gut.

class A{ 
    @Inject private RetryServiceCaller retryServiceCaller; 
} 

Aber jetzt das Problem ist, dass, da diese neue Klasse A Singleton ist, muss ich die retryServiceCaller jedes Mal klonen, dass jemand diese Klasse A. verwenden

Ive FactoryModuleBuilder untersucht, es zu benutzen und Erstellen Sie eine Factory für diese Klasse. Aber da die Klasse Parameter aus der Konfigurationsdatei hat, konnte ich den Weg nicht finden, der es funktioniert.

So etwas wie dieses

class A{ 
     @Inject private RetryServiceCaller.Factory retryServiceCallerFactory; 

    } 

Da ist in meinem RetryServiceCaller implementieren diese

public interface Factory { 
    @Inject 
    RetryServiceCaller create(); 
} 


@Inject 
public RetryServiceCaller(int maxRetryAttempts, int upperBoundary, int lowerBoundary, long multiplicationFactor, int timeout, int incrementTimeout) { 
    this.maxRetryAttempts = maxRetryAttempts; 
    this.upperBoundary = upperBoundary; 
    this.lowerBoundary = lowerBoundary; 
    this.multiplicationFactor = multiplicationFactor; 
    this.timeout = timeout; 
    this.incrementTimeout = incrementTimeout; 
} 

Aber guice mir Fehler auswerfen sagen

No implementation for com.proxy.handlers.RetryServiceCaller$Factory was bound 

Antwort

1

Guice kann automatisch eine Null-Argument-Fabrik bereitstellen: Anstatt Foo zu injizieren, können Sie immer Provider<Foo> injizieren. Auf diese Weise können Sie fooProvider.get() aufrufen, um jederzeit und überall eine Instanz zu erstellen. Sie müssen nicht an Provider binden oder eine Provides-Methode verwenden, um Zugriff darauf zu erhalten; Sie können Foo oder Provider<Foo> injizieren, ob Sie einen bind(...).to(...) Typ Bindung verwenden, eine toProvider Bindung, eine toInstance Bindung, ein @Provides Verfahren, oder irgendetwas anderes, und Guice get oder gibt eine internes Provider automatisch aufruft.

(Der zurück Provider wird auch Bereiche respektieren, so dass Sie Ihre @Singleton Umfang um Drop benötigen, um auf mehr als eine Instanz zu erhalten, und sich bewusst sein, dass toInstance Bindungen werden immer die gleiche Instanz zurück.)

Dies ist kein Job für FactoryModuleBuilder; Verwenden Sie FactoryModuleBuilder nur dann, wenn Sie die Konstruktorparameter des gleichen Typs mischen müssen.

Ihre fertigen Bindung sollte wie folgt aussehen:

@Provides 
/* NOT @Singleton */ 
RetryServiceCaller provideMaxRetryAttempts(@Named("config") JsonObject config) throws IOException { 
    JsonObject retryDetails = config.getJsonObject("retry_details"); 
    return new RetryServiceCaller(retryDetails.getInteger("maxRetryAttempts"), retryDetails.getInteger("upperBoundary"), retryDetails.getInteger("lowerBoundary"), 
            retryDetails.getLong("multiplicationFactor"), retryDetails.getInteger("timeout"), retryDetails.getInteger("increaseTimeout")); 
} 

Und in Ihrer Klasse:

@Inject public YourCallerConsumer(Provider<RetryServiceCaller> callerProvider) { 
    this.callerProvider = callerProvider; 
} 

public void doAction() { 
    RetryServiceCaller newCaller = callerProvider.get(); 
    // interact with caller 
} 
1

Ihre erste Ansatz sollte gut funktionieren. Wenn Sie nicht möchten, dass RetryServiceCaller ein Singleton ist, entfernen Sie die Annotation @Singleton von der Provider-Methode, und für jeden Injektionspunkt wird eine neue Instanz erstellt.

Assisted Inject könnte auch hier funktionieren, aber es ist Overkill. Wenn Sie möchten, diesen Weg zu gehen:

interface RetryServiceCallerFactory { 
    RetryServiceCaller create(String configParam1, String configParam2); 
} 

public class RetryServiceCaller { 
    @AssistedInject 
    public RetryServiceCaller(String configParam1, String configParam2) {} 
} 

dann in Ihrem Modul

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

und in Ihren Anspritzpunkten

@Inject RetryServiceCallerFactory factory; 

RetryServiceCaller create(JsonObject config) { 
    return factory.create(config.getFirstParam(), config.getSecondParam()); 
} 

Sie zum documentation für umfangreichere Beispiele verweisen.