16

使用 Guice,如果我有

@Inject @Named("light")
Color light;

我可以用

bind(Color.class).annotatedWith(Names.named("light"))
    .toInstance(new Color("white"));

如果 Color 构造函数只需要颜色名称,则将其绑定到白色。

但是,如果 Color 构造函数还需要由 Guice 创建的对象,我该怎么做呢?例如:

@Inject
public Color(ColorSet colorset, String colorName) {...}

其中颜色集由 Guice 在运行时创建,在 configure(){...} 中不可用。

我想这样做没有:

  • 为我需要注入的每种颜色创建一个类/子类(如 WhiteColor)
  • 直接在我的代码中使用反射
  • 更改我的课程以使用ColorFactoy factory; factory.get("light");而不是@Named("light") Color light;
4

3 回答 3

34

做到这一点的最好方法不是使用工厂,而是使用@Provides方法。我的公司非常非常广泛地使用 Guice,并且requestInjection总是被认为是一个坏主意,因为它可以很容易地建立一个非常脆弱的隐式依赖关系图。

它应该是这样的:

public class FooModule extends AbstractModule {
  protected void configure() {
    // do configuration
  }

  @Provides
  @Named("white")
  Color provideWhiteColor(ColorSet colorSet) {
    return colorSet.white(); // or whatever
  }

  @Provides
  @Named("black")
  Color provideBlackColor(ColorSet colorSet) {
    return colorSet.black(); // or whatever
  }

  // etc
}
于 2012-09-06T23:18:48.593 回答
4

您可以在模块中设置一个工厂,并在其上请求注入以填充 ColorSet。

模块:

ColorFactory colorFactory = new ColorFactory();

requestInjection(colorFactory);

bind(Color.class).annotatedWith(Names.named("light")).toInstance(colorFactory.buildColor("white"));
bind(Color.class).annotatedWith(Names.named("dark")).toInstance(colorFactory.buildColor("black"));

颜色工厂:

public class ColorFactory {

    private ColorSet colorSet;

    public Color buildColor(String color){
        return new Color(colorSet, color);
    }

    @Inject
    public void setColorSet(ColorSet colorSet) {
        this.colorSet = colorSet;
    }
}
于 2012-09-05T22:12:37.867 回答
1

在很少的代码库中,我看到直接使用注入器来获取某些对象。

injector.getInstance(Color.class);

在这种情况下,您可以使用以下内容:

injector.getInstance(Key.get(Color.class, Names.named("light")));
于 2020-12-14T07:17:41.230 回答