Guice可以断言单例不是直接实例化的吗?

Jos*_*ver 1 java dependency-injection guice

如果我尝试构造单例的新实例,Guice是否可能抛出异常?

例如:

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!
    }
}
Run Code Online (Sandbox Code Playgroud)

通过将MySingleton构造函数包私有化,我可以限制错误的范围,但是当然同一个包中的类仍然可以使用扳手.这里的优点是我的单元测试AnotherRightWay可以轻松地将模拟传递MySingleton给它的构造函数.

或者,我可以使MySingleton构造函数受到保护,Guice可以处理,我仍然可以通过使我的模拟扩展来进行模拟MySingleton.但是,MySingleton用户可以在不知道危险的情况下做同样的事情.

如果Guice可以抛出异常,我可以在单元测试中使用反射来构造模拟,但我的用户不会轻易地创建非单例版本的MySingleton.

这可能吗?我应该使用包私有还是受保护并学会爱炸弹?

Vla*_*eev 5

Guice并不神奇.你不能强迫它做一些事情Injector,所以不,你不能这样做,事实上你不应该这样做.

正如您已经注意到的,最好的方法是创建MySingletonpackage-private的构造函数.这样,除了Guice之外,没有人能够构建它.由于此程序包由您控制,因此可以安全地假设没有人会MySingleton通过Guice以其他方式创建(当然,使用您的模块).

这不是"炸弹".Package-private修饰符完全用于此目的.假设控制你的包,所以可以使构造函数和其他东西包装为私有,并假设没有人,你会调用它们.