9

我目前正在构建一个基于 Dropwizard + Guice + Jersey 的应用程序,其中数据库访问暂时由 JDBI 处理。

我想要实现的是拥有典型的企业架构,其中资源访问服务类访问 DAO 类,该类又访问数据库。以适当的 DI 方式将所有这些连接起来会很好,尽管我想如果其他所有方法都失败了,我可以在应用程序的 run() 方法中构建我的对象图。

所以,我遇到了之前在这里提到的这个问题:获取 DBIFactory 需要环境和配置,它们需要在 Guice 执行其注入魔法时而不是在 run()-time 时可用.

作为一个 Dropwizard 和 Guice 菜鸟,到目前为止,我设法整合的是我的 DAO 对象需要一个 Provider,这与

public class UserDAOProvider implements Provider<UserDAO> {

    @Inject
    Environment environment;
    @Inject
    Configuration configuration;

    @Override
    public UserDAO get() {
        final DBIFactory factory = new DBIFactory();
        final (MyConfiguration) config = (MyConfiguration) configuration;
        DBI jdbi = null;
        try {
            jdbi = factory.build(environment, config.getDataSourceFactory(),
                    "mysql");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return jdbi.onDemand(UserDAO.class);
    }

}

将其注册为单例提供程序应该让我将 UserDAO 注入我的服务中。

现在,我们如何真正将环境注入到 Provider 中?目前我被困在 Guice 抱怨没有为环境找到合适的构造函数,所以它试图实例化它而不是从 Dropwizard 本身获取它。

看起来这是可行的;有一个dropwizard-guice包,我认为它的 DropWizardEnvironmentModule 是我需要的。但我觉得我只是在这里错过了一些难题,以了解如何将事物组合在一起。到目前为止,我还没有找到一个完整的工作示例......

4

3 回答 3

4

这就是我在 Dropwizard 中使用 Guice 的方式。在您的 run() 方法中添加该行

Guice.createInjector(new ConsoleModule()); 

您不能注入 Environ

创建类 ConsoleModule

public class ConsoleModule extends AbstractModule {

    //configuration and env variable declaration

    public  ConsoleModule(ConsoleConfiguration consoleConfig, Environment env)
    {
        this.consoleConfig = consoleConfig;
        this.env= env;
    }

    protected void configure()
    {
        //You should not inject Configuration and Environment in your provider since you are mixing     
        //dropwizard framework stuff with Guice.Neverthless you will have to bind them in the below order

        bind(Configuration.class).toInstance(consoleConfig.class);
        bind(Environment.class).toInstance(env.class);
        bind(UserDAO.class).toProvider(UserDAOProvider.class).in(Singleton.class);
    }
}
于 2014-08-31T02:46:53.013 回答
4

我遇到了与 OP 相同的问题,但使用的是 Hibernate 而不是 JDBI。不过,我的简单解决方案适用于 JDBI - 只需切换DBIFactorySessionFactory.

首先在 Guice 模块中为单例 SessionFactory 添加注入提供程序:

public class MyModule extends AbstractModule {

    private SessionFactory sessionFactory;

    @Override
    protected void configure() {
    }

    @Provides
    SessionFactory providesSessionFactory() {

        if (sessionFactory == null) {
             throw new ProvisionException("The Hibernate session factory has not yet been set. This is likely caused by forgetting to call setSessionFactory during Application.run()");
        }

       return sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
}

您需要SessionFactory从应用程序的 run() 方法中设置单例。在您的情况下,使用 JDBI,您可以在将 DBIFactory 交给 Guice 模块之前创建和配置它:

public void run(MyConfiguration configuration, Environment environment) {

    myModule.setSessionFactory(hibernateBundle.getSessionFactory());
    ...
}

现在 SessionFactory 可以在任何需要的地方注入。我现在对我的 DAO 类使用隐式绑定,只需使用 @Inject 注释构造函数并注入 SessionFactory 单例。我没有明确地为 DAO 类创建提供程序:

@Singleton
public class WidgetDAO extends AbstractDAO<App> {

    @Inject
    public WidgetDAO(SessionFactory factory) {
        super(factory);
    }

    public Optional<Widget> findById(Long id) {
        return Optional.fromNullable(get(id));
    }
    ...
}

现在我可以将我的 DAO 单例实例注入到资源中:

@Path("/widgets")
@Produces(MediaType.APPLICATION_JSON)
public class WidgetsResource {

    private final WidgetDAO widgetDAO;

    @Inject
    public WidgetsResource(WidgetDAO widgetDAO) {
        this.widgetDAO = widgetDAO;
    }
    ...
}

请注意,此方法遵循仅注入直接依赖项的 Guice 建议。不要仅仅为了创建 DBI 工厂而尝试注入 Envrionment 和 Configuration - 注入预构建的 DBI 工厂本身。

于 2015-01-22T12:16:27.667 回答
0

我们有相同的配置(dw-jdbi-guice),还有一个抽象的“基”Application类,它使事情变得更加复杂。

由于在run方法期间发生了很多事情,而且很多事情都取决于配置对象,我们最终在 run 方法中创建了注入器。但是由于我们bootsrap还需要来自(例如 ObjectMapper)的对象,所以我们最终List<Module>在 Application 类中有一个字段。不是最漂亮的解决方案,但可以处理各种场景。

于 2014-11-25T21:02:04.603 回答