简体   繁体   English

这个Guice示例中发生了什么?

[英]What's going on in this Guice example?

I've got the following code example. 我有以下代码示例。

public interface Calculator {
    public int compute(int a);
}

public class Adder implements Calculator {
    private int n = 0;

    @Override public int compute(int a) {
        int result = a + n;
        ++n;
        return result;
    }
}

public class X {@Inject public void run(Calculator c) {
        System.out.println(c.compute(500));
    }
}
public class FirstModule extends AbstractModule {@Override protected void configure() {
        bind(Calculator.class).to(Adder.class);
    }
}

public static void main(String[] args) {
    Injector inj = Guice.createInjector(new FirstModule());
    X x1 = inj.getInstance(X.class);
    x1.run(inj.getInstance(Calculator.class));
    X x2 = inj.getInstance(X.class);
    x2.run(inj.getInstance(Calculator.class));
    System.out.println(x1 == x2);
}

I expected the output to be: 我期望输出为:

500
500
False

and instead it is: 而是:

500
500
500
500
False

It seems that the instantiation lines (like X x1 = inj.getInstance(X.class); ) execute the run() method. 似乎实例化行(如X x1 = inj.getInstance(X.class); )执行run()方法。 Why is that? 这是为什么?

Guice indeed does call run , because you tell it to: Guice确实会调用run ,因为您告诉它:

public class X { /* here -> */ @Inject public void run(Calculator c) {
        System.out.println(c.compute(500));
    }
}

The @Inject annotation of the run method makes Guice think that this is a setter, so it injects a calculator instance into your class using run , when it injects the members during instance creation. run方法的@Inject注释使Guice认为这是一个设置器,因此当它在实例创建过程中注入成员时,会使用run将计算器实例注入到您的类中。

See documentation . 请参阅文档

Guice does not only inject constructors, annotated with @Inject but also fields annotated with @Inject and methods annotated with @Inject . 吉斯不仅注入构造,标注了@Inject也与领域注解@Inject和带注释的方法@Inject

For example (besides the timing/order) these examples lead to the same result, namely foo being injected: 例如(除了时间/顺序之外),这些示例导致相同的结果,即foo被注入:

class ConstructorInjection {
    private String foo;

    @Inject public ConstructorInjection(String foo) { this.foo = foo; }
}

class FieldInjection {
    @Inject private String foo;

    // default constructor not needed in this case
}

class MethodInjection {
    private String foo;

    // default constructor not needed in this case

    @Inject
    public void setFoo(String foo) { this.foo = foo; }
}

Note that Guice does not imply any naming conventions on methods to inject (so the setter setFoo could have been named run or anything else as well. Guice will inject all methods annotated with @Inject . 请注意,Guice并不暗示要注入的方法的任何命名约定(因此,设置程序setFoo可能也被命名为run或其他任何名称setFoo将注入所有@Inject注释的方法。

You are basically using the third way (MethodInjection) which will cause Guice to call run when the instance is created. 基本上,您正在使用第三种方法(MethodInjection),这将在创建实例时使Guice调用run

As Girish shows in his/her answer, you'd have to use constructor injection (or field injection) in your case, have a field for the calculator in your class and remove the parameter from the run method. 正如Girish在他/她的答案中所示,您必须在这种情况下使用构造函数注入(或字段注入),在类中为计算器提供一个字段,并从run方法中删除参数。

@Inject will execute the contructor/method you have specified. @Inject将执行您指定的构造函数/方法。 Correct way of using it is with constructor to inject Calc instance. 正确的使用方法是与构造函数一起注入Calc实例。

    interface Calculator
{
    public int compute(int a);
}

class Adder implements Calculator
{
    private int n = 0;

    @Override
    public int compute(int a)
    {
        int result = a + n;
        ++n;
        return result;
    }
}

class X
{
    private Calculator c;

    @Inject
    public X(Calculator c)
    {
        this.c = c;
    }

    public void run(Calculator c)
    {
        System.out.println(c.compute(500));
    }
}
class FirstModule extends AbstractModule
{
    @Override
    protected void configure()
    {
        bind(Calculator.class).to(Adder.class);
    }
}

public static void main(String[] args)
    {
        Injector inj = Guice.createInjector(new FirstModule());
        X x1 = inj.getInstance(X.class);
        x1.run(inj.getInstance(Calculator.class));
        X x2 = inj.getInstance(X.class);
        x2.run(inj.getInstance(Calculator.class));
        System.out.println(x1 == x2);
    }

Output: 输出:

500 500 false 500500错误

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM