使用带有DAO模式的Guice进行依赖注入

时间:2022-09-25 10:58:37

For a small side project I'm working on I've been trying to implement something of a DAO pattern for my interactions with the DB, and have started using Guice (for my first time) to handle the DI for me. Right now I have this class hierarchy:

对于我正在研究的小型项目,我一直在努力为我与DB的交互实现一些DAO模式,并且已经开始使用Guice(我第一次)为我处理DI。现在我有这个类层次结构:

使用带有DAO模式的Guice进行依赖注入

DAOImpl takes a reference to a class type so my database client (mongo/morphia) can do some initialization work and instantiate a BasicDAO provided by morphia. Here's snippets of the relevant classes:

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

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);
  }
}

I know that I need to tell Guice to bind the relevant classes for each generic DAOImpl that gets extended, but I'm unsure of how to do it. This looks like it might have been answered but it's not clicking for me. I've tried some of the following:

我知道我需要告诉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>>() {});
  }
}

These are some of the the errors I've seen:

这些是我见过的一些错误:

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)

Any help would be much appreciated.

任何帮助将非常感激。

1 个解决方案

#1


2  

If you want an injection site like the following:

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

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

to be injected with an instance of your UserDAO class then

然后注入您的UserDAO类的实例

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

is the correct syntax.

是正确的语法。

As for your other error:

至于你的其他错误:

1) No implementation for org.mongodb.morphia.Datastore was bound.

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

This is because Datastore is an interface. You need to bind the interface to an implementation, an instance, or a Provider<Datastore>.

这是因为Datastore是一个接口。您需要将接口绑定到实现,实例或Provider

To work out how to do this, think of the steps you would need to do this manually without the extra complication of Guice. Once you 100% understand this, you can try and design an object graph that appropriately reflects the steps in the initialization of morphia.

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

To get you started, the morphia quick tour has a guide on how to get an instance of the Datastore object:

为了帮助您入门,morphia快速浏览提供了有关如何获取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();

From their code, you can see that there are at least two dependencies required to get the Datastore:

从他们的代码中,您可以看到获取数据存储区至少需要两个依赖项:

  1. A singleton Morphia
  2. 单身形态

  3. A singleton MongoClient
  4. 单身MongoClient

You will have to write some code to set this up, possibly using Guice's Provider class.

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

#1


2  

If you want an injection site like the following:

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

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

to be injected with an instance of your UserDAO class then

然后注入您的UserDAO类的实例

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

is the correct syntax.

是正确的语法。

As for your other error:

至于你的其他错误:

1) No implementation for org.mongodb.morphia.Datastore was bound.

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

This is because Datastore is an interface. You need to bind the interface to an implementation, an instance, or a Provider<Datastore>.

这是因为Datastore是一个接口。您需要将接口绑定到实现,实例或Provider

To work out how to do this, think of the steps you would need to do this manually without the extra complication of Guice. Once you 100% understand this, you can try and design an object graph that appropriately reflects the steps in the initialization of morphia.

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

To get you started, the morphia quick tour has a guide on how to get an instance of the Datastore object:

为了帮助您入门,morphia快速浏览提供了有关如何获取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();

From their code, you can see that there are at least two dependencies required to get the Datastore:

从他们的代码中,您可以看到获取数据存储区至少需要两个依赖项:

  1. A singleton Morphia
  2. 单身形态

  3. A singleton MongoClient
  4. 单身MongoClient

You will have to write some code to set this up, possibly using Guice's Provider class.

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