0
votes

I have a class Xyz which is injected into multiple classes. I use Guice for DI.

    class Xyz{
        
        static int i =0;
        
        public Xyz(){
          System.out.println("###########creating instance = " + (++i));
        }
    }
   

    class ManagedOne{
    
         Xyx xyz;
        
        public ManagedOne(Xyz xyz){
         this.xyz = xyz;
        }
    }

    class ManagedTwo{
    
        Xyx xyz;
    
        public ManagedTwo(Xyz xyz){
         this.xyz = xyz;
        }
    }

Guice

  bind(Xyz.class).in(Singleton.class);
  bind(ManageOne.class).in(Singleton.class);
  bind(ManageTwo.class).in(Singleton.class);
  
  1. Now even if i remove the about binding i still see that Guice is creating singleton instance of Xyz. Verified using the sysout. It only prints it one with value 1. Is this the default behavior? I thought default was factory.
  2. Will Guice inject same instance of Xyz in both the managers? If yes, Is the code bind(Xyz.class).in(Singleton.class) redundant then?

Note that i donot use injector.getInstance(Xyz.class) to get instance of Xyz all the time. Rather i do it the way i showed in my code above

1
You didn't provide the full and correct definition of Xyz: the first line you wrote is class Xyz() { with () that shouldn't be here. So I guess you adapted your code shown. Also after I removed the (), I ran your code with var injector = Guice.createInjector(); injector.getInstance(Xyz.class); injector.getInstance(Xyz.class); injector.getInstance(Xyz.class); and got the expected result ###########creating instance = 1 ###########creating instance = 2 ###########creating instance = 3 Therefore please provide a MCVE - Olivier Grégoire
This is a sample code and not actual code that i run in my system since actual code is quite complex. I edit the post. Also note that i donot create instance of Xyz using injector. See my updated post. - user93796
The default binding is for factories; what you've posted should work. Note that ManageOne and ManageTwo will actually need to be created themselves in order for Guice to create Xyz, so if you don't make it a point to create instances of both ManagedOne and ManagedTwo, you won't see the counter increase. - Jeff Bowman

1 Answers

2
votes

I don't see any issue.

Given that count is static, make sure that your entire app is not called twice, that you don't have several injectors or similar. Or even that you don't call new Xyz() by hand.

I made two tests in one. Abc is not annotated with @Singleton, while Xyz is annotated with @Singleton.

import com.google.inject.*;

public class Main {

  public static void main(String[] args)  {
    var injector = Guice.createInjector();
    var module1 = injector.getInstance(Module1.class);
    var module2 = injector.getInstance(Module2.class);
    if (module1.abc == module2.abc) {
      System.out.println("Only one instance of Abc");
    } else {
      System.out.println("Two instances of Abc");
    }
    if (module1.xyz == module2.xyz) {
      System.out.println("Only one instance of Xyz");
    } else {
      System.out.println("Two instances of Xyz");
    }
  }

  static class Abc {
    static int count = 0;
    Abc() { System.out.println("Abc #" + ++count); }
  }

  @Singleton static class Xyz {
    static int count = 0;
    Xyz() { System.out.println("Xyz #" + ++count); }
  }

  @Singleton static class Module1 {
    final Abc abc;
    final Xyz xyz;
    @Inject Module1(Abc abc, Xyz xyz) { this.abc = abc; this.xyz = xyz; }
  }

  @Singleton static class Module2 {
    final Abc abc;
    final Xyz xyz;
    @Inject Module2(Abc abc, Xyz xyz) { this.abc = abc; this.xyz = xyz; }
  }

}

The result is the following:

Abc #1
Xyz #1
Abc #2
Two instances of Abc
Only one instance of Xyz

If this doesn't answer your question, please make a MCVE that exactly showcases your issue rather than vaguely explaining.