我目前正在构建一个基于Dropwizard + Guice + Jersey的应用程序,目前该数据库访问由JDBI处理。
我要实现的目标是拥有典型的企业体系结构,其中资源访问服务类访问DAO类,而DAO类又访问数据库。最好以正确的DI方式进行所有连接,尽管我猜如果其他所有方法都失败了,我可以在应用程序的run()方法中构建对象图。
因此,我遇到了在这里提到的这个问题before:获取DBIFactory既需要环境,又需要配置,这在Guice进行注入(inject)魔术时而不是在run()时需要以某种方式可用。 。
作为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注入(inject)我的服务中。
现在,我们如何实际将环境注入(inject)提供者?目前,我一直在Guice提示无法为环境找到合适的构造函数,因此它正在尝试实例化它,而不是从Dropwizard本身中获取它。
看来这是可行的。我认为有dropwizard-guice软件包,其DropWizardEnvironmentModule是我所需要的。但是我觉得我只是想了解如何将事物组合在一起而在这里遗漏了一些难题。到目前为止,我还没有找到一个完整的工作示例...
最佳答案
我遇到了与OP相同的问题,但使用的是Hibernate而不是JDBI。不过,我的简单解决方案适用于JDBI-只需将DBIFactory
切换为SessionFactory
即可。
首先在您的Guice模块中为单例SessionFactory添加一个注入(inject)提供程序:
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;
}
}
您需要从应用程序的run()方法设置单例
SessionFactory
。在您的情况下,使用JDBI,可以在将其移交给Guice模块之前创建和配置DBIFactory:public void run(MyConfiguration configuration, Environment environment) {
myModule.setSessionFactory(hibernateBundle.getSessionFactory());
...
}
现在,SessionFactory可以在任何需要的地方注入(inject)。现在,通过仅使用@Inject注释构造函数并注入(inject)SessionFactory单例,即可对DAO类使用隐式绑定(bind)。我没有明确为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单例实例注入(inject)资源中:
@Path("/widgets")
@Produces(MediaType.APPLICATION_JSON)
public class WidgetsResource {
private final WidgetDAO widgetDAO;
@Inject
public WidgetsResource(WidgetDAO widgetDAO) {
this.widgetDAO = widgetDAO;
}
...
}
请注意,此方法遵循Guice建议的仅注入(inject)直接依赖项的建议。不要只是为了注入(inject)环境和配置而试图创建DBI工厂-而是注入(inject)预先构建的DBI工厂本身。
关于dependency-injection - Dropwizard和Guice : injecting Environment,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25581590/