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

时间:2014-03-24 09:16:17

标签: 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!
    }
}

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

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

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

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

1 个答案:

答案 0 :(得分:5)

Guice不是魔法。你不能强迫它做Injector以外的事情,所以不,你不能这样做,事实上你不应该这样做。

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

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