【问题标题】:Dependency injection using Guice with the DAO pattern使用带有 DAO 模式的 Guice 进行依赖注入
【发布时间】:2016-11-17 04:33:53
【问题描述】:

对于我正在进行的一个小型项目,我一直在尝试为我与数据库的交互实现某种 DAO 模式,并开始使用 Guice(我第一次)为我处理 DI。现在我有这个类层次结构:

DAOImpl 引用一个类类型,因此我的数据库客户端(mongo/morphia)可以进行一些初始化工作并实例化 morphia 提供的BasicDAO。以下是相关类的 sn-ps:

public class DAOImpl<T> implements DAO<T> {
  private static final Logger LOG = LoggerFactory.getLogger(DAOImpl.class);
  private static final String ID_KEY = "id";
  private final org.mongodb.morphia.dao.DAO morphiaDAO;

  @Inject
  public DAOImpl(Datastore ds, Class<T> resourceClass) {
    morphiaDAO = new BasicDAO(resourceClass, ds);

    LOG.info("ensuring mongodb indexes for {}", resourceClass);
    morphiaDAO.getDatastore().ensureIndexes(resourceClass);
  }
}

public class UserDAO extends DAOImpl<User> {
  @Inject
  public UserDAO(Datastore ds) {
    super(ds, User.class);
  }

  public User findByEmail(String email) {
    return findOne("email", email);
  }
}

我知道我需要告诉 Guice 为每个扩展的通用 DAOImpl 绑定相关类,但我不确定该怎么做。这看起来可能已经得到回答,但它并没有为我点击。我尝试了以下一些方法:

public class AppInjector extends AbstractModule {
  @Override
  protected void configure() {
    bind(com.wellpass.api.dao.DAO.class).to(DAOImpl.class);

//    bind(new TypeLiteral<SomeInterface<String>>(){}).to(SomeImplementation.class);
//    bind(new TypeLiteral<MyGenericInterface<T>>() {}).to(new TypeLiteral<MyGenericClass<T>>() {});
//    bind(new TypeLiteral<DAO<User>>() {}).to(UserDAO.class);

    bind(new TypeLiteral<DAO<User>>(){}).to(new TypeLiteral<DAOImpl<User>>() {});
  }
}

这些是我看到的一些错误:

com.google.inject.CreationException: Unable to create injector, see the following errors:

1) No implementation for org.mongodb.morphia.Datastore was bound.
  while locating org.mongodb.morphia.Datastore
    for the 1st parameter of com.wellpass.api.dao.UserDAO.<init>(UserDAO.java:12)
  at com.wellpass._inject.AppInjector.configure(AppInjector.java:18)

2) java.lang.Class<T> cannot be used as a key; It is not fully specified.
  at com.wellpass.api.dao.DAOImpl.<init>(DAOImpl.java:19)
  at com.wellpass._inject.AppInjector.configure(AppInjector.java:14)

任何帮助将不胜感激。

【问题讨论】:

    标签: java generics types guice dao


    【解决方案1】:

    如果您想要如下注射部位:

    @Inject
    public DAOConsumer(DAO<User> dao) {
    }
    

    然后注入UserDAO 类的实例

    bind(new TypeLiteral<DAO<User>>() {}).to(UserDAO.class);
    

    correct syntax

    至于你的其他错误:

    1) 没有绑定 org.mongodb.morphia.Datastore 的实现。

    这是因为Datastore 是一个接口。您需要将接口绑定到实现、实例或Provider&lt;Datastore&gt;

    要弄清楚如何执行此操作,请考虑手动执行此操作所需的步骤,而不需要 Guice 的额外复杂性。一旦您 100% 理解这一点,您就可以尝试设计一个对象图,以适当地反映 morphia 初始化的步骤。

    为了帮助您入门,morphia quick tour 提供了有关如何获取 Datastore 对象实例的指南:

    final Morphia morphia = new Morphia();
    
    // tell Morphia where to find your classes
    // can be called multiple times with different packages or classes
    morphia.mapPackage("org.mongodb.morphia.example");
    
    // create the Datastore connecting to the default port on the local host
    final Datastore datastore = morphia.createDatastore(new MongoClient(), "morphia_example");
    datastore.ensureIndexes();
    

    从他们的代码中可以看出,要获取Datastore至少需要两个依赖:

    1. 单身Morphia
    2. 单身MongoClient

    您必须编写一些代码来设置它,可能使用 Guice 的 Provider 类。

    【讨论】:

    • 嘿,只是想回圈说声谢谢。我通过自己手动注入 deps 开始了新的老式方法,并一步一步地解决问题。你对TypeLiteral 的回答让我大部分时间都在那里,但由于我的DAO 是一个由DAOImpl 实现的接口,所以最终对我有用:bind(new TypeLiteral&lt;DAOImpl&lt;User&gt;&gt;() { }).to(UserDAO.class); bind(new TypeLiteral&lt;DAOImpl&lt;Person&gt;&gt;() { }).to(PersonDAO.class); bind(Mongo.class).to(MongoClient.class);
    • 对于Datastore,我最终制作了一个像你建议的提供者并使用@Singleton 注释:@Provides @Singleton public Datastore datastoreProvider(MongoClient mongoClient, ServerConfig config) { Morphia morphia = new Morphia(); return morphia.createDatastore(mongoClient, config.getMongoConfig().getDatabase()); }
    • @Justin 很高兴它有帮助 - 祝你申请的其余部分好运!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多