0

我有一个从数据库加载一些数据的@Singleton 类。Singleton 在引导期间加载,但是构造函数从 DAO 数据加载类中抛出异常。我从来没有看到这个异常,我假设是因为 Guice 的单例引导加载正在吞噬它。有没有更好的方法来做到这一点,以便我至少可以看到堆栈跟踪或异常消息?我希望不必对课程了解太多,但也许一旦我用@Singleton 标记了它,我应该知道在抛出异常之前记录它?

4

1 回答 1

3

我建议不要让您的单身人士尝试在其构造函数中从数据库加载数据。一般来说,构造函数不应该工作。在构造函数中工作会使您的代码更难测试(因为在您调用对象上的任何方法之前,您需要构造它)。如果创建注入器,它也会减慢进程,并使注入器创建过程变得脆弱,因为依赖关系图中的细微变化会导致初始化以不同的顺序发生。

一种解决方案是使用Guava Service抽象。您在启动时需要做的任何工作都发生在服务中。服务绑定使用Multibinder.newSetBinder().

为此,您的 main 方法组装模块,创建主类,并在该主类上调用一个方法。您将在主类中注入一个ServiceManager ,然后入口方法启动服务。

这是一个例子

@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类来简化这一点。AbstractModulebindService(Class<? extends Service>)

如果您愿意让您的单例类扩展AbstractIdleService,您可以进一步简化这一点,但这会将Service接口中的方法添加到您的单例的公共 API 中。

于 2015-03-02T00:20:02.920 回答