Dependency injection 使用HK2进行基元类型的依赖项注入(在运行时决定)

Dependency injection 使用HK2进行基元类型的依赖项注入(在运行时决定),dependency-injection,primitive-types,hk2,Dependency Injection,Primitive Types,Hk2,因此,基本上,我有一种情况,我想将基元类型注入到一个类中(即,一个字符串和一个整数)。您可以将应用程序的URL和端口号作为示例输入。我有三个部分: 现在假设我有一个类,它接受这些参数: public class PrimitiveParamsDIExample { private String a; private Integer b; public PrimitiveParamsDIExample(String a, Integer b) { this.a = a;

因此,基本上,我有一种情况,我想将基元类型注入到一个类中(即,一个字符串和一个整数)。您可以将应用程序的URL和端口号作为示例输入。我有三个部分:

现在假设我有一个类,它接受这些参数:

public class PrimitiveParamsDIExample {

  private String a;
  private Integer b;

  public PrimitiveParamsDIExample(String a, Integer b) {
    this.a = a;
    this.b = b;
  }
}
所以我的问题很简单。如何将
a
b
注入类
primitiveparamsdiesample

一般来说,这也是询问如何注入在运行时决定的参数。如果我有上面的a和b,从STDIN或输入文件读取,它们显然会因运行而异

更重要的是,我如何在HK2框架内完成上述工作

编辑[02/23/15]:@jwells131313,我尝试了你的想法,但我得到了以下错误(这一个用于字符串参数;类似于int):

我的课程设置和你的答案一模一样。我还重写了
toString()
方法,在
PrimitiveParamsDIExample
中打印变量
a
b
。然后,我在我的Hk2Module类中添加了以下内容:

public class Hk2Module extends AbstractBinder {
    private Properties properties;

    public Hk2Module(Properties properties){
      this.properties = properties;
    }

    @Override
    protected void configure() {
          bindFactory(StringAFactory.class).to(String.class).in(RequestScoped.class);
          bindFactory(IntegerBFactory.class).to(Integer.class).in(RequestScoped.class);
          bind(PrimitiveParamsDIExample.class).to(PrimitiveParamsDIExample.class).in(Singleton.class);
    }
}
现在,我创建了一个测试类,如下所示:

@RunWith(JUnit4.class)
public class TestPrimitiveParamsDIExample extends Hk2Setup {

    private PrimitiveParamsDIExample example;

    @Before
    public void setup() throws IOException {
        super.setupHk2();
        //example = new PrimitiveParamsDIExample();
        example = serviceLocator.getService(PrimitiveParamsDIExample.class);
    }

    @Test
    public void testPrimitiveParamsDI() {
        System.out.println(example.toString());
    }
}
public class Hk2Setup extends TestCase{
    // the name of the resource containing the default configuration properties
    private static final String DEFAULT_PROPERTIES = "defaults.properties";
    protected Properties config = null;
    protected ServiceLocator serviceLocator;
    public void setupHk2() throws IOException{
        config = new Properties();
        Reader defaults = Resources.asCharSource(Resources.getResource(DEFAULT_PROPERTIES), Charsets.UTF_8).openBufferedStream();
        load(config, defaults);
        ApplicationHandler handler = new ApplicationHandler(new MyMainApplication(config));
        final ServiceLocator locator = handler.getServiceLocator();
        serviceLocator = locator;
    }

    private static void load(Properties p, Reader r) throws IOException {
        try {
            p.load(r);
        } finally {
            Closeables.close(r, false);
        }
    }
}
其中,HK2设置如下:

@RunWith(JUnit4.class)
public class TestPrimitiveParamsDIExample extends Hk2Setup {

    private PrimitiveParamsDIExample example;

    @Before
    public void setup() throws IOException {
        super.setupHk2();
        //example = new PrimitiveParamsDIExample();
        example = serviceLocator.getService(PrimitiveParamsDIExample.class);
    }

    @Test
    public void testPrimitiveParamsDI() {
        System.out.println(example.toString());
    }
}
public class Hk2Setup extends TestCase{
    // the name of the resource containing the default configuration properties
    private static final String DEFAULT_PROPERTIES = "defaults.properties";
    protected Properties config = null;
    protected ServiceLocator serviceLocator;
    public void setupHk2() throws IOException{
        config = new Properties();
        Reader defaults = Resources.asCharSource(Resources.getResource(DEFAULT_PROPERTIES), Charsets.UTF_8).openBufferedStream();
        load(config, defaults);
        ApplicationHandler handler = new ApplicationHandler(new MyMainApplication(config));
        final ServiceLocator locator = handler.getServiceLocator();
        serviceLocator = locator;
    }

    private static void load(Properties p, Reader r) throws IOException {
        try {
            p.load(r);
        } finally {
            Closeables.close(r, false);
        }
    }
}
因此,在某个地方,接线混乱,我得到了一个不满意的例外。我没有正确连接的是什么


谢谢

有两种方法可以做到这一点,但其中一种还没有文档化(尽管它是可用的……我想我需要再次编写文档……)

我要走第一条路

基本上,你可以使用HK2

通常,当您开始生成字符串、整数、long和标量时,您需要对它们进行限定,因此让我们从两个限定符开始:

@Retention(RUNTIME)
@Target( { TYPE, METHOD, FIELD, PARAMETER })
@javax.inject.Qualifier
public @interface A {}

然后写下你的工厂:

@Singleton // or whatever scope you want
public class StringAFactory implements Factory<String> {

    @PerLookup // or whatever scope, maybe this checks the timestamp?
    @A // Your qualifier
    public String provide() {
        // Write your code to get your value...
        return whatever;
    }

    public void dispose(String instance) {
        // Probably do nothing...
    }
}
注意我把整数改为int,好吧。。。就因为我能。您也可以以相同的方式使用字段注入或方法注入。这里是字段注入,方法注入是读者的练习:

public class PrimitiveParamsDIExample {
  @Inject @A
  private String a;

  @Inject @B
  private int b;

  public PrimitiveParamsDIExample() {
  }
}
有几种方法可以约束工厂

在活页夹中:

使用自动类分析:


活页夹外的EDSL:

谢谢您的解释!下面的代码示例给出了一个很好的答案。我要去装订厂。今晚我也会测试一下这个想法,然后再继续。不过,作为一个补充:你不认为它有很多代码只用于阅读简单的原语吗?同意StringAFactory和IntegerFactory可以重复使用。但我可能会开发新的方法,在一个类一个类的基础上处理我的字符串和整数。这意味着我必须编写尽可能多的工厂来处理ctor输入基元类型。我同意,如果有很多值要读取,这种方法就无法扩展。因此,您可能希望使用目前正在开发但尚未准备就绪的持久性工具。我根据您的想法使用测试编辑了我的答案。你看了之后告诉我。
public class PrimitiveParamsDIExample {

  private String a;
  private int b;

  @Inject
  public PrimitiveParamsDIExample(@A String a, @B int b) {
    this.a = a;
    this.b = b;
  }
}
public class PrimitiveParamsDIExample {
  @Inject @A
  private String a;

  @Inject @B
  private int b;

  public PrimitiveParamsDIExample() {
  }
}