2014-09-03 2 views
3

У меня есть этот интерфейс и простая реализация:Guice помощь инъекционные несколько фабричных методов и нулевых параметров

public interface Data {  
} 

import java.nio.file.Path; 
import javax.annotation.Nullable; 
import javax.inject.Inject; 
import com.google.inject.assistedinject.Assisted; 

public class SimpleData implements Data { 
    @Inject 
    public SimpleData(@Assisted @Nullable Path path) { 
    } 
} 

Я хочу, чтобы создать Factory с различными способами, используя Guice.

import java.nio.file.Path; 

import javax.annotation.Nullable; 

public interface Factory { 
    Data create(); 
    Data load(@Nullable Path path); 
} 

Но следующая конфигурация модуля:

import com.google.inject.Guice; 
import com.google.inject.Injector; 
import com.google.inject.assistedinject.FactoryModuleBuilder; 

public class Main { 
    public static void main(String[] args) { 
     Injector injector = Guice.createInjector(
       binder -> binder.install(
          new FactoryModuleBuilder().implement(Data.class, SimpleData.class) 
                 .build(Factory.class))); 
     Data data = injector.getInstance(Factory.class).create(); 
    } 
} 

терпит неудачу:

Exception in thread "main" com.google.inject.CreationException: Guice creation errors: 

    1) No implementation for java.nio.file.Path annotated with @com.google.inject.assistedinject.Assisted(value=) was bound. 
     while locating java.nio.file.Path annotated with @com.google.inject.assistedinject.Assisted(value=) 
     for parameter 0 at SimpleData.<init>(SimpleData.java:10) 
     at Factory.create(Factory.java:1) 
     at com.google.inject.assistedinject.FactoryProvider2.initialize(FactoryProvider2.java:539) 
     at com.google.inject.assistedinject.FactoryModuleBuilder$1.configure(FactoryModuleBuilder.java:335) 

    1 error 
     at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:435) 
     at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:175) 
     at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:109) 
     at com.google.inject.Guice.createInjector(Guice.java:95) 
     at com.google.inject.Guice.createInjector(Guice.java:72) 
     at com.google.inject.Guice.createInjector(Guice.java:62) 
     at Main.main(Main.java:9) 

ответ

7

Я решил свою проблему с помощью аннотации @AssistedInject. Цитата из Javadoc:

При использовании в тандеме с FactoryModuleBuilder, конструкторы аннотированные с @AssistedInject показывают, что несколько конструкторов могут быть введены, каждый с различными параметрами.

Так я добавить аннотацию и конструктор в SimpleData класс:

public class SimpleData implements Data { 
    @AssistedInject 
    public SimpleData(@Assisted Path path) { 

    } 
    @AssistedInject 
    public SimpleData() { 

    } 
} 

я удалил @Nullable аннотацию с завода:

import java.nio.file.Path; 

public interface Factory { 
    Data create(); 
    Data load(Path path); 
} 
2

@Nullable не означает, что если у вас нет привязки, то null будет закачиваться. Только позволяет записывать привязки до null. Если у вас нет привязки и нет соответствующего JIT-привязки, тогда инъекция завершится неудачей.

Метод вашей фабрики create() требует, чтобы Guice нашел привязку @Assisted Path, но, очевидно, не может найти ее, так как вы ее никогда не создавали, поэтому она терпит неудачу.

Честно говоря, я не уверен, есть ли чистый способ реализовать такие дефолты. В идеале вы должны отметить Path с некоторой привязкой аннотации и добавить привязку по умолчанию к null для него, но @Assisted уже является аннотацией привязки, и невозможно иметь несколько аннотаций привязки в одной точке инъекции. Вы можете попробовать создать привязку для @Assisted Path:

binder.bind(Path.class).annotatedWith(Assisted.class).toInstance(null); 

Однако, я не уверен, если это будет работать, потому что Assisted может быть особенным Guice. И даже если это будет работать, оно не очень чистое - могут быть конфликты с другими вспомогательными заводами, принимающими Path с.

+0

Спасибо за вашу помощь. Я нашел [решение] (http://stackoverflow.com/a/25738517/1594933) с помощью '@ AssistedInject'. – gontard

0

У меня бы Guice реализовать какой-то внутренний интерфейс фабрики, а затем разоблачить что-то еще. Как это:

interface InternalFactory { 
    Data load(@Nullable Path path); 
} 

public interface Factory { 
    Data load(); 
    Data load(@Nullable Path path); 
} 

class FactoryImpl implements Factory { 
    @Inject InternalFactory internalFactory; 

    @Override 
    public Data load() { 
     return load(null); // Pass your defaults here 
    } 

    @Override 
    public Data load(@Nullable Path path) { 
     // Sadly you'll have to explicitly forward arguments here, but it's not 
     // too bad IMO 
     return internalFactory.load(path); 
    } 
} 

public class MyModule extends AbstractModule { 
    @Override 
    protected void configure() { 
     install(new FactoryModuleBuilder() 
       .implement(Data.class, SimpleData.class) 
       .build(InternalFactory.class)); 

     bind(Factory).to(FactoryImpl.class); 
    } 
} 
+0

Спасибо за помощь. Я нашел [решение] (http://stackoverflow.com/a/25738517/1594933) с помощью '@ AssistedInject'. – gontard

Смежные вопросы