Frage

Is it possible for Guice throw an exception if I try to construct a new instance of a singleton?

For example:

public class MyModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(MySingleton.class).in(Singleton.class);
    }
}

@Singleton
public class MySingleton {
    MySingleton() { /* ... */ }
}

public class RightWay {
    public void withInjector() {
        Injector injector = Guice.createInjector(new MyModule());
        MySingleton mySingleton = injector.getInstance(MySingleton.class);
    }
}

public class AnotherRightWay {
    private final MySingleton mySingleton;

    @Inject
    public AnotherRightWay(MySingleton mySingleton) {
        this.mySingleton = mySingleton;
    }
}

public class TheWrongWay {
    public void directInstantiation() {
        MySingleton mySingleton = new MySingleton(); // I want an exception here!
    }
}

By making MySingleton's constructor package private, I can limit the scope for mistakes, but of course classes in the same package can still throw a spanner into the works. The advantage here is that my unit tests for AnotherRightWay can easily pass mocks of MySingleton to its constructor.

Or, I could make MySingleton's constructor protected, which Guice can handle, and I can still mock by making my mocks extend MySingleton. But then a MySingleton user could do the same without knowing the danger.

If Guice can throw an exception, I can use reflection in my unit tests to construct mocks, but my users could not easily accidentally create a non-singleton version of MySingleton.

Is this possible? Should I just use either the package-private or protected and learn to love the bomb?

War es hilfreich?

Lösung

Guice is not magic. You can't force it to do something outside of an Injector, so no, you can't do that, and in fact you shouldn't.

The best way, as you have already noticed, is to make constructor of MySingleton package-private. That way no one outside of the package will be able to construct it but Guice. Since this package is controlled by you, it is safe assumption that no one will create MySingleton in other way than via Guice (using your module, of course).

This is not a "bomb". Package-private modifier is intended exactly for this purpose. It is assumed that you control your packages, so it is fine to make constructors and other things package-private and assume that no one but you will call them.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top