2013-02-08 20 views
5

Tôi có một POJO đơn giản:tiêm tên Guice singleton

public class MyPOJO { 
    @Inject 
    private Fizz fizz; 

    private Buzz buzz; 

    // rest of class omitted for brevity 
} 

Tôi muốn cấu hình mô-đun Guice của tôi như vậy là có hai loại Fizz es rằng nó sẽ tiêm nhiễm:

  1. Một đặc biệt, phiên bản toàn cầu-singleton Fizz; và
  2. khác (không đặc biệt) Fizz trường

Tôi muốn MyPOJO được tiêm với các trường hợp đặc biệt/singleton. Vì vậy, tôi đổi mã của tôi:

public class MyPOJO { 
    @Inject @Named("Special-Fizz") 
    private Fizz fizz; 

    private Buzz buzz; 

    // rest of class omitted for brevity 
} 

Sau đó, trong mô-đun của tôi:

public class MyModule extends AbstractModule { 
    @Override 
    public void configure() { 
     bind(Fizz.class).annotatedWith(
      Names.named("Special-Fizz")) 
      .to(Fizz.class); 

     // Other bindings here... 
    } 

    @Provides @Singleton 
    private Fizz providesFizz() { 
     return new Fizz(true, "Special", 12.0); 
    } 
} 

Nhưng khi tôi cố gắng để kiểm tra đơn vị (JUnit 4.10) này:

public class MyTest { 
    @Named("Special-Fizz") private Fizz specialFizz; 

    @Test 
    public void usingNamedShouldInjectSpecialFizz() { 
     MyModule mod = new MyModule(); 
     Injector injector = Guice.createInjector(mod); 

     specialFizz = injector.getInstance(Fizz.class); 

     Assert.assertTrue(specialFizz != null); 
    } 
} 

này đi. Càng xa càng tốt. Nhưng sau đó nếu tôi thay đổi tên của trường specialFizz:

@Named("Special-Fuzz-This-Shouldnt-Work") private Fizz specialFizz; 

Và tái chạy thử nghiệm, nó vẫn đi. Tại sao?!? Tôi sẽ đi lạc ở đâu? Cảm ơn trước.

Trả lời

3

Rất kỳ quặc. Guice nên khiếu nại nếu nó không thể tìm thấy một ràng buộc Named rằng nó tiêm. Tôi là một chút bối rối bởi thử nghiệm của bạn, mặc dù. Tôi không biết những gì injector.inject nào. Bạn có nghĩa là injectMembers? Nó có thể có ý nghĩa hơn để thực sự có được một thể hiện của POJO của bạn và chắc chắn rằng nó làm việc theo cách bạn mong đợi. Có thể một cái gì đó như:

public class FizzTest { 

    public static class MyModule extends AbstractModule { 
    @Override 
    protected void configure() { 
    } 

    @Provides 
    @Singleton 
    @Named("Special-Fizz") 
    public Fizz providesFizz() { 
     return new Fizz(true); 
    } 
    } 

    public static class Fizz { 
    boolean special = false; 
    public Fizz() {} 
    public Fizz(boolean special) { 
     this.special = special; 
    } 
    } 

    public static class MyPOJO { 
    @Inject @Named("Special-Fizz") 
    private Fizz fizz; 

    @Inject 
    private Fizz otherFizz; 
    } 

    @Test 
    public void test() { 
    MyModule mod = new MyModule(); 
    Injector injector = Guice.createInjector(mod); 

    MyPOJO pojo = injector.getInstance(MyPOJO.class); 
    assertTrue(pojo.fizz.special); 
    assertTrue(!pojo.otherFizz.special); 
    } 

} 
+0

Cảm ơn @condit (+1) - đó là lỗi của tôi khi nhập câu hỏi này. Tôi đã chỉnh sửa câu hỏi ban đầu của mình để cho thấy rằng tôi thực sự đang gọi 'injector.getInstance', không phải là' injector.inject'. Điều đó có thay đổi gì cho bạn không? 'GetInstance' có đúng không cho tôi sử dụng ở đây không? Nếu vậy, tại sao, và cái gì? Cảm ơn một lần nữa! – IAmYourFaja

+0

Trong thử nghiệm của bạn, bạn đang yêu cầu các vòi phun cho một thể hiện của 'Fizz' mà nó sẽ luôn luôn có thể cung cấp cho bạn (vì phương pháp' @ Provides') của bạn. Tôi nghĩ rằng bạn muốn có một ví dụ của 'MyPOJO' thay thế. Lưu ý rằng 'Fizz' bạn nhận được không liên quan đến thành viên' Fizz' của bài kiểm tra. Vì vậy, việc thay đổi '@ Named' sẽ không có hiệu lực trong trường hợp này. – condit

+0

Bạn đã đóng đinh nó. Tôi chỉ yêu cầu nó tiêm một 'MyPOJO' và nó tiêm nó một cách chính xác nó là tài sản 'Fizz' với fizz đặc biệt của tôi. Bí ẩn được giải quyết - chỉ là một phương pháp thử nghiệm được thực hiện kém. Cảm ơn một lần nữa! – IAmYourFaja

2

Guice nhìn thấy phương pháp @Provides và vui vẻ sử dụng phương pháp đó để tiêm Fizz. Nếu bạn muốn có một trường hợp đặc biệt của Fizz, bạn có thể thả các chú thích từ phương pháp providesFizz() và thay vào đó ràng buộc với

bind(Fizz.class) 
    .annotatedWith(Names.named("Special-Fizz") 
    .toInstance(providesFizz()); 

Bằng cách này, bạn nói với Guice chính xác Fizz để sử dụng như là "đặc biệt-Fizz", trong khi vẫn để nó tiêm Fizz "bình thường" nếu không.

Tuyên bố từ chối: Tôi chưa thực sự thử thiết lập như của bạn, nhưng tôi đã sử dụng một thiết bị tương tự. Hãy cho tôi biết nếu nó hoạt động hay không.

+0

Cảm ơn @Bradley T. Hughes (+1) - ** tuy nhiên ** đề xuất của bạn không thay đổi bất cứ điều gì. Các bài kiểm tra đơn vị vẫn đi qua, bất kể những gì bạn đặt tên là 'Fizz'. Bạn đã đề cập đến một cái gì đó mà tôi nghĩ là thú vị. Bạn đã nói "* Tôi chưa thực sự thử thiết lập như của bạn ... *", tuy nhiên, từ câu trả lời của bạn, tôi cho rằng bạn có vẻ khá thoải mái khi sử dụng Guice. Tôi nghĩ rằng điểm * của Guice là sử dụng các lớp và chú thích với nhau để xác định chính xác loại/cấu hình bạn muốn tiêm ... – IAmYourFaja

+0

.. Tôi có đang làm điều gì đó ở đây ngoài sự bình thường không? Nếu vậy, tại sao?!? Tôi đang hiểu lầm cách sử dụng Guice thông thường ở đâu? Cảm ơn một lần nữa! – IAmYourFaja

+0

Tôi không nghĩ đó là một thiết lập kì quái. Và thành thật mà nói, tôi đã không sử dụng Guice nhiều, vì vậy tôi chắc chắn không có chuyên gia.Sự khác biệt là mã tôi đang làm việc trên sử dụng cùng một chú thích để tiêm hai loại khác nhau (một cá thể riêng lẻ của mỗi loại). –