1

我有以下代码示例。

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

我预计输出是:

500
500
False

相反,它是:

500
500
500
500
False

似乎实例化行(如X x1 = inj.getInstance(X.class);)执行该run()方法。这是为什么?

4

2 回答 2

1

@Inject 将执行您指定的构造函数/方法。使用它的正确方法是使用构造函数注入 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);
    }

输出:

500 500 错误

于 2014-07-17T10:22:54.237 回答
1

Guice 确实调用run,因为你告诉它:

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

run 方法的@Inject注解让 Guice 认为这是一个 setter,所以run当它在实例创建期间注入成员时,它使用 将计算器实例注入到您的类中。

请参阅文档

Guice 不仅注入带有注释的构造函数,@Inject还注入带有注释的字段和带有注释的@Inject方法@Inject

例如(除了时间/顺序)这些示例导致相同的结果,即 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; }
}

请注意,Guice 并不暗示要注入的方法有任何命名约定(因此 settersetFoo可能已命名run或其他任何名称。Guice 将注入所有用@Inject.

您基本上使用的是第三种方式(MethodInjection),这将导致 Guice 在run创建实例时调用。

正如 Girish 在他/她的回答中显示的那样,您必须在您的情况下使用构造函数注入(或字段注入),在您的类中有一个用于计算器的字段,并从 run 方法中删除参数。

于 2014-07-17T09:56:53.420 回答