注入名为Guice的单身人士

时间:2013-02-08 21:38:25

标签: java dependency-injection junit guice

我有一个简单的POJO:

public class MyPOJO {
    @Inject
    private Fizz fizz;

    private Buzz buzz;

    // rest of class omitted for brevity
}

我想配置我的Guice模块,以便它注入两种类型的Fizz es:

  1. 一个特殊的全局单例Fizz实例;和
  2. 其他(非特殊)Fizz个实例
  3. 我希望MyPOJO注入特殊/单例实例。所以我修改了我的代码:

    public class MyPOJO {
        @Inject @Named("Special-Fizz")
        private Fizz fizz;
    
        private Buzz buzz;
    
        // rest of class omitted for brevity
    }
    

    然后在我的模块中:

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

    但是当我尝试单元测试(JUnit 4.10)时:

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

    这过去了。到现在为止还挺好。但是,如果我更改specialFizz字段的名称:

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

    重新运行测试,仍然通过。为什么?!?我在哪里误入歧途?提前谢谢。

2 个答案:

答案 0 :(得分:4)

很奇怪。 Guice如果找不到它注入的Named绑定就应该抱怨。不过,我对你的测试感到有些困惑。我不知道injector.inject做了什么。你的意思是injectMembers?实际获得POJO的实例并确保它以您期望的方式工作可能更有意义。也许是这样的:

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

}

答案 1 :(得分:2)

Guice看到了@Provides方法,并愉快地使用它来注入Fizz。如果您想要一个特殊的Fizz实例,可以从providesFizz()方法中删除注释,而不是与

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

通过这种方式,您可以告诉Guice确切地使用哪个Fizz作为“Special-Fizz”,同时仍然允许它正常注入“{1}}”。

免责声明:我实际上没有尝试像你这样的设置,但我使用了一个类似的设置。让我知道它是否有效。