HK2的依赖注入原始类型(在运行时决定)

时间:2015-02-19 20:45:50

标签: dependency-injection primitive-types hk2

所以基本上,我有一种情况,我想将原始类型注入一个类(即一个字符串和一个整数)。您可以将应用程序的URL和端口号视为示例输入。我有三个组成部分:

现在说我有一个班级,它确实考虑了这些参数:

public class PrimitiveParamsDIExample {

  private String a;
  private Integer b;

  public PrimitiveParamsDIExample(String a, Integer b) {
    this.a = a;
    this.b = b;
  }
}

所以我的问题很简单。如何将ab注入课程PrimitiveParamsDIExample

通常,这也是询问如何注入在运行时决定的参数。如果我有上面的a和b,从STDIN或输入文件中读取,它们显然会在不同的运行中运行。

此外,我如何在HK2框架内完成上述工作?

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

org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=String,parent=PrimitiveParamsDIExample,qualifiers

我完全按照你的答案设置课程。我还覆盖了toString()方法,以在a中打印变量bPrimitiveParamsDIExample。然后,我在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());
    }
}

其中,Hk2Setup如下:

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

所以在某个地方,为了得到一个UnsatisfiedDependencyException,连线很乱。我没有正确连接什么?

谢谢!

1 个答案:

答案 0 :(得分:2)

有两种方法可以做到这一点,但有一种方法尚未记录(虽然它可用......我想我需要再次处理文档......)

我将在这里通过第一种方式。

基本上,您可以使用HK2 Factory

通常当你开始生成字符串和整数以及像这样的long和scalars时,你可以限定它们,所以让我们从两个限定符开始:

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

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

然后写你的工厂:

@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...
    }
}

和整数:

@Singleton // or whatever scope you want
public class IntegerBFactory implements Factory<Integer> {

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

    public void dispose(String instance) {
        // Probably do nothing...
    }
}

现在让我们重新做你原来的类来接受这些值:

public class PrimitiveParamsDIExample {

  private String a;
  private int b;

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

注意我将Integer改为int,好吧......因为我可以。您也可以以相同的方式使用场注入或方法注入。这里是现场注入,方法注入是读者的练习:

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

  @Inject @B
  private int b;

  public PrimitiveParamsDIExample() {
  }
}

有几种方法可以绑定工厂。

在活页夹中:bindFactory

使用自动类分析:addClasses

活页夹外的EDSL:buildFactory