2012-02-11 77 views
28

我有一個工廠下面的構造函數,傳遞參數與吉斯

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

} 

這是foo的定義:

class Foo 
{ 
    Foo(String bar) 
    { 

    } 

} 

確定。我不知道我怎麼可以將這個參數傳遞給Foo與Guice的構造函數?

任何想法?

回答

43

所有「Guice構造函數參數」答案在某種程度上似乎不完整。 這裏是一個完整的解決方案,包括用法:

interface FooInterface{ 
    String getFooName(); 
} 

//註釋構造函數和輔助參數的實現類

class Foo implements FooInterface { 
    String bar; 

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

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

} 

//使用,需要一個create()方法工廠接口只有輔助參數。 // FooFactory接口沒有明確的實現類(吉斯魔術)

interface FooFactory{ 
    Foo create(String bar); 
} 

//該工廠綁定到

binderModule implements Module{ 

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

通過AssistedInject

創建了提供商//現在使用它:

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!" 
    } 
} 

的很多幫助這裏:https://google.github.io/guice/api-docs/latest/javadoc/index.html?com/google/inject/assistedinject/FactoryModuleBuilder.html

+0

不適合我。我有* NullPointerException *,因爲從未調用過* Foo *構造函數。可能你需要在某個地方使用你的*模塊* – 2013-02-12 23:01:41

+0

請修復「create」方法(FooFactory接口)缺失的返回類型。 它必須是:Foo create(String bar); – frhack 2016-04-29 07:42:49

1

如果這個類是一個工廠,它應該是一個吉斯管理對象,具有非靜態的getFoo方法,和的getFoo方法只是將使用

new Foo(bar) 

不是每個類都需要由吉斯被實例化。

另請參閱AssistedInject,避免自己創建該工廠,讓Guice爲您創建一個工廠。

8

你可能要找的是使用Guice工廠。 AssistedInject功能特別容易,但他們有一個manual example at the top of the page。手動示例的缺點是,您在非靜態方法getFoo中獲得工廠,您可以將任何參數傳遞給您需要的參數,並從此處構建對象。

如果您在Foo中有攔截方法,這將不會直接工作,但它可以在其他許多情況下使用。

要使用AssistedInject,這對我有幾分更清楚的語義,並意味着更少的人工接線,你會當創建Foo(當然,FooImpl,我們應該使用接口)需要guice-assistedinject擴展的類路徑,則:

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

然後創建一個FooFactory接口:

public interface FooFactory { 
    public Foo create(String bar); 
} 
您吉斯模塊中

然後:

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

您可以查看javadoc for FactoryModuleBuilder瞭解更復雜工廠的示例。

+0

是的,它很糟糕,結構圖比guice更靈活。 – DarthVader 2012-02-11 18:40:30

+0

我可以在哪裏下載StructureMap for Java? – mark 2012-08-03 12:52:54

+0

這對我很有效,雖然它不是很漂亮。 – 2014-12-29 23:41:09

4

我知道THA這是舊線程,但我今天就自己遇到了這個問題。 我只需要兩個或最多三個不同的'Foo'實例,我真的不想寫出Factory的所有bolierplate代碼。 隨着一點谷歌搜索,我發現這Stubbisms – Tony’s Weblog我會建議這個解決方案,這是完美的,如果你確切知道你需要什麼樣的實例。

在吉斯模塊:

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

或者在Java 8:

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

而且在服務的構造函數,你需要的Foo實例:

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

和Foo我案例:

public class FooImpl implements Foo { 

    private String name; 

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

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

希望它可以幫助別人。