【问题标题】:Guice: Using @Named to create objectGuice:使用@Named 创建对象
【发布时间】:2012-09-05 21:37:39
【问题描述】:

使用 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;

【问题讨论】:

    标签: java dependency-injection guice


    【解决方案1】:

    最好的方法不是使用工厂,而是使用@Provides methods。我的公司非常非常广泛地使用 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
    }
    

    【讨论】:

    • 这是个好主意,也许我也可以将它与 Modules.override().with() 混合使用以重用它们。
    • 这很有帮助 - 知道如何使用 Guice 注入器来获取任一实例吗?寻找类似Guice.createInjector(FooModule).getInstance(Color.class) 但规格为“白色”或“黑色”的东西..
    • 我不确定您将如何使用@Named,但无论如何您都应该使用绑定注释 (github.com/google/guice/wiki/BindingAnnotations)。然后你可以说 injector.getInstance(Key.get(Color.class, Black.class)) (尽管我可能在某处缺少通用类型规范)。 getInstance(...) 被重载以获取 Key (google.github.io/guice/api-docs/latest/javadoc/index.html?com/…),而不仅仅是一个类。
    【解决方案2】:

    您可以在模块中设置一个工厂,并在其上请求注入以填充 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;
        }
    }
    

    【讨论】:

    • 哦,我读到了,因为您不想要每种颜色的子类(即:WhiteColor)。您是否还想参考其他颜色?
    • 您能说明一下您对 ColorSet 的使用吗?
    • 这只是真实情况的简化示例。没有颜色集,有一个由 guice 创建和连接的对象图。
    • 你的颜色被认为是不可变的吗?
    • 不,但是如果我让它们不可变会有帮助吗?
    【解决方案3】:

    我见过很少的代码库直接使用注入器来获取特定对象。

    injector.getInstance(Color.class);
    

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

    injector.getInstance(Key.get(Color.class, Names.named("light")));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-28
      • 2013-07-01
      相关资源
      最近更新 更多