我有一个@Singleton类,可以从数据库中加载一些数据。 Singleton在引导期间加载,但构造函数从DAO数据加载类中抛出异常。我从来没有看到过这个异常,我假设是因为Guice的单身自举加载吞噬了它。有没有更好的方法来做到这一点,我至少可以看到堆栈跟踪或异常消息?我希望不必过多地了解这个课程,但也许一旦我用@Singleton标记它,我应该知道在抛出之前记录异常?
答案 0 :(得分:3)
我建议不要让你的单身人士尝试从数据库的构造函数中加载数据。一般来说,构造者不应该工作。在构造函数中完成工作会使代码更难测试(因为在调用对象上的任何方法之前,需要构造它)。如果使用注入器,它也会减慢进程的速度,并使注入器创建过程变得脆弱,因为依赖关系图中的细微更改将导致初始化以不同的顺序发生。
一种解决方案是使用Guava Service抽象。您在启动时需要完成的任何工作都在服务中进行。服务使用Multibinder.newSetBinder()
绑定。
为此,main方法组装模块,创建主类,并在该主类上调用一个方法。您可以在主类中注入ServiceManager,并且entry方法启动服务。
这是一个例子
@Singleton
public class MySingleton {
private final FooDao dao;
private final List<Foo> foos = new ArrayList<>();
@Inject
MySingleton(FooDao dao) {
this.dao = dao;
}
@VisibleForTesting
void initialize() {
foos.addAll(dao.getAllFoos());
}
private static class StartupService extends AbstractIdleService {
private final MySingleton singleton;
@Inject
StartupService(MySingleton singleton) {
this.singleton = singleton;
}
@Override protected void startUp() {
singleton.initialize();
}
}
public static class Module extends AbstractModule {
@Override protected void configure() {
Multibinder.newSetBinder(binder(), Service.class)
.addBinding().to(StartupService.class);
}
}
}
您可以通过创建扩展ServiceModule
并添加AbstractModule
方法的可重复使用的bindService(Class<? extends Service>)
类来简化此操作。
如果您愿意使单件类扩展AbstractIdleService
,则可以进一步简化此操作,但这会将Service
接口中的方法添加到您的单例的公共API中。