2012-02-11 32 views
28

tôi có một nhà máy như dưới đây,tham số Pass tới constructor với Guice

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

} 

Đây là định nghĩa Foo:

class Foo 
{ 
    Foo(String bar) 
    { 

    } 

} 

OK. Tôi không chắc làm thế nào tôi có thể vượt qua tham số này để Foo constructor với Guice?

Bất kỳ ý tưởng nào?

Trả lời

43

Tất cả câu trả lời "Tham số Constructor" có vẻ không đầy đủ theo một cách nào đó. Đây là một giải pháp hoàn chỉnh, bao gồm việc sử dụng:

interface FooInterface{ 
    String getFooName(); 
} 

// Chú thích các nhà xây dựng và các thông số hỗ trợ trên lớp thực hiện

class Foo implements FooInterface { 
    String bar; 

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

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

} 

// Tạo một giao diện nhà máy với một phương pháp tạo() mà mất chỉ các thông số được hỗ trợ. // FooFactory giao diện không có một lớp thực hiện rõ ràng (Guice kỳ diệu)

interface FooFactory{ 
    Foo create(String bar); 
} 

// Bind nhà máy đó để một nhà cung cấp tạo ra bởi AssistedInject

binderModule implements Module{ 

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

// Bây giờ sử dụng nó:

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

Rất nhiều giúp ở đây: https://google.github.io/guice/api-docs/latest/javadoc/index.html?com/google/inject/assistedinject/FactoryModuleBuilder.html

+0

Không hoạt động đối với tôi. Tôi có * NullPointerException * bởi vì * Foo * constructor không bao giờ gọi. Có lẽ bạn cần sử dụng * Module * của bạn ở đâu đó? –

+0

Vui lòng sửa kiểu trả về thiếu của phương thức "create" (giao diện FooFactory). Phải là: Tạo Foo (Thanh chuỗi); – frhack

1

Nếu lớp này là một nhà máy, nó phải là một đối tượng Guice quản lý, có một phương pháp getFoo phi tĩnh, và phương pháp getFoo sẽ chỉ sử dụng

new Foo(bar) 

Không phải mọi lớp cần phải được khởi tạo bởi Guice .

Cũng xem AssistedInject, để tránh tự tạo nhà máy này và để Guice tạo một nhà máy cho bạn.

8

Điều bạn đang tìm kiếm là sử dụng nhà máy Guice. Đặc biệt dễ dàng với chức năng AssistedInject, nhưng chúng có manual example at the top of the page. Ngắn gọn của nó cho ví dụ hướng dẫn sử dụng là bạn nhận được các nhà máy theo phương pháp không tĩnh getFoo mà bạn vượt qua bất kỳ thông số nào mà bạn cần và xây dựng đối tượng từ đó.

Điều này sẽ không hoạt động trực tiếp nếu bạn có phương pháp chặn trong Foo, nhưng nó sẽ hoạt động trong nhiều trường hợp khác.

Để sử dụng AssistedInject, mà với tôi có ngữ nghĩa hơi sạch và phương tiện hệ thống dây điện ít sử dụng, bạn sẽ cần phần mở rộng guice-assistedinject trong classpath, sau đó khi tạo Foo (tốt, FooImpl, chúng ta nên sử dụng các giao diện):

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

Sau đó, bạn tạo một giao diện FooFactory:

public interface FooFactory { 
    public Foo create(String bar); 
} 

Sau đó, trong mô-đun Guice của bạn:

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

Bạn có thể xem javadoc for FactoryModuleBuilder để biết ví dụ về các nhà máy phức tạp hơn.

+0

vâng, nó rất tệ, nó rất phức tạp, structuremap linh hoạt hơn nhiều so với guice. – DarthVader

+0

Tôi có thể tải Sơ đồ Cấu trúc cho Java ở đâu? – mark

+0

Điều này làm việc cho tôi, mặc dù nó không phải là rất đẹp. –

4

tôi biết tha t đây là chủ đề cũ nhưng tôi chỉ cần nhấn vấn đề bản thân mình ngày hôm nay. Tôi chỉ cần hai hoặc tối đa ba trường hợp khác nhau của 'Foo' và tôi thực sự không muốn viết tất cả mã bolierplate của Nhà máy. Với một chút googling tôi tìm thấy điều này Stubbisms – Tony’s Weblog Tôi sẽ đề nghị giải pháp này là hoàn hảo nếu bạn biết chính xác những trường hợp bạn cần.

Trong Guice mô-đun:

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

Hoặc trong java 8:

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

Và trong constructor của dịch vụ của bạn, nơi bạn cần Foo trường hợp:

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

Và Foo trong tôi trường hợp:

public class FooImpl implements Foo { 

    private String name; 

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

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

Hy vọng nó sẽ giúp ai đó.

Các vấn đề liên quan