Search code examples
javadependency-injectionguice

Guice - How to make a class with no args constructor singleton and let the variables auto injected?


I have below code sample

public interface MyDao {
    ...
}

public class MyDaoImpl implements MyDao {
    ...
}

public class MyService {
    @Inject
    private MyDao myDao;

    ...
}

public class MyModule extends AbstractModule {
    @Override
    public void configure() {
        bind(MyDao.class).to(MyDaoImpl.class).in(Singleton.class);
    }
}

In main class, I have

Injector injector = Guice.createInjector(new MyModule());
MyService myService = injector.getInstance(MyService.class);
MyService myService2 = injector.getInstance(MyService.class);

myService and myService2 are different objects.

If I add below code in MyModule

@Provides
@Singleton
public MyService getMyService() {
    return new MyService();
}

myService and myService2 become same object, but the variable myDao becomes null.

How can I make MyService singleton and let the variable myDao auto injected without changing the constructor of MyService?


Solution

  • In the example you gave, you are generating the MyService by simply calling its constructor, rather than injection.

    To solve your problem, you can bind your service in the configuration and create it with the call to getInstance

    public class MyModule {
        @Override
        public void configure() {
            bind(MyDao.class).to(MyDaoImpl.class).in(Singleton.class);
            bind(MyService.class).in(Singleton.class);
        }
    }
    

    Note that, as stated by chrylis, it would be a better solution to change the constructor or add a setter for your MyDao object in the MyService class. If you ever have to create your object without injection or even have to change injection framework, that would save you an incommensurable amount of time.