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. Why is that?
Guice indeed does call run
, because you tell it to:
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.
See documentation .
Guice does not only inject constructors, annotated with @Inject
but also fields annotated with @Inject
and methods annotated with @Inject
.
For example (besides the timing/order) these examples lead to the same result, namely foo being injected:
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
.
You are basically using the third way (MethodInjection) which will cause Guice to call run
when the instance is created.
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.
@Inject will execute the contructor/method you have specified. Correct way of using it is with constructor to inject Calc instance.
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.