有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何使用自定义参数配置提供程序?

我的类依赖于一些服务,这些服务需要获取一些参数,然后进行网络调用,目前我正在传递这些参数,然后通过注入类中的工厂创建这些服务。我需要将这些服务作为依赖项注入,我知道我可以为它们创建提供者,但在大多数示例中,我看到提供者通常绑定到固定值,如serveraddres等,但我需要在运行时提供这些值

下面是我的示例代码:

public SomeClass {
   private final SomeFactory someFactory;

   @Inject
   SomeClass(SomeFactory factory) {
      someFactory = factory;
   }

   public Foo getFoo(String fooId) {
      FooService fooService = someFactory.getFooService(fooId);
      return fooService.getFoo();
   }

}

我需要做的是:

public SomeClass {
   private final FooService fooService;

   @Inject
   SomeClass(FooService fooService) {
      this.fooService = fooService;
   }

   public Foo getFoo(String fooId) {
      return fooService.getFoo();
   }

}

更新1

使用例更加清晰:

  @Provides
  @RequestScoped
  public SomeService provideSomeService(Dep1 dep1, String code) throws IOException {
    return new SomeService.Builder()
        .withApplicationName("Foo")
        .setCode(code)  
        .build();
  }

在这里,code在默认情况下可以是null,需要时我可以在其中给出一些值

我是否可以在创建提供程序之前以某种方式将参数传递给该提供程序


共 (2) 个答案

  1. # 1 楼答案

    如果你的值有一个绑定(这里,code是一个没有绑定注释的字符串),那么你的更新1就是代码的样子

    在实践中,有一些区别:

    • intString值这样的常量通常用绑定注释@Named或自定义注释进行注释
    • 如果在Guice初始化之后需要向对象图中注入一个值,但是有足够深的对象图,依赖项注入仍然是一个好主意,那么可以创建一个child injector。通过这种方式,您可以在一个操作或对象中访问@Named("code") String,但不能在整个Guice应用程序中访问
    • 如果code的值是动态的,无法通过Guice作为自己的键提供,那么必须使用某种工厂将其传递进来。对于一个基于构建器的对象,我认为您的SomeFactory实现是我在您的情况下想到的最好的实现

    如果您不需要使用生成器,并且可以让Guice根据字段或构造函数参数创建对象,那么可以通过代码生成工厂

    • Guice可以通过FactoryModuleBuilder在一个称为"assisted injection"的功能中为您生成工厂
    • 谷歌的另一个工具AutoFactory将通过代码生成一个工厂实现,可以在Guice和Dagger中工作。(它捆绑为“Auto”,其中包括一个名为AutoValue的模型对象生成器,该生成器还生成注释实现。)

    我在my other SO answer here中展示了一个儿童注射器和辅助注射的小演示

  2. # 2 楼答案

    这里最好的方法是参数化模块,并将参数传递给在运行时创建的提供程序:

    public class MyModule extends AbstractModule {
      private final String code;
    
      public MyModule(String code) {
        this.code = code;
      }
    
      @Override public void configure() {
        Provider<Dep1> depProvider = getProvider(Dep1.class);
        bind(SomeService.class)
            .toProvider(() -> new SomeService.Builder()
                .withApplicationName("Foo")
                .withDep(depProvider.get())
                .setCode(code)  
                .build())
            .in(RequestScoped.class);
      }
    }