如何为数据对象创建范围的Guice提供程序?

时间:2011-06-12 04:37:17

标签: java guice

我的问题是,如何使用guice提供程序的功能(它们的范围实例的能力),数据对象?

以下是基本原理:我有一个会话范围的类WebPage,它根据来自数据库对象DAO的Web请求获取数据。

//Scope of WebPage: SESSION
class WebPage{
  Provider<DAO> daoProvider; //Scope of DAO: REQUEST

  WebPage(Provider<DAO> daoProvider){
     this.daoProvider = daoProvider;
  }

  public String getMyString(){
    return daoProvider.get().getMyString();
  }

  public int getMyInt(){
    return daoProvider.get().getMyInt();
  }
}

WebPage对象是Web框架的一部分,它将所有页面对象保持在会话中。在每个请求getMyStringgetMyInt方法被多次调用以获取值之后,在页面上向用户显示它们之前。假设DAO对象附加到表中的一个特定行,只是从该行中提取数据。

出于性能原因,我需要daoProvider始终返回相同的实例,以避免每次调用getMyStringgetMyInt时重新连接到数据库。另一方面,实例必须跨请求进行更新,以便在页面刷新后对用户显示对数据库的任何更新。

所以我要找的是会话范围DAO对象中WebPage的请求范围提供程序。问题是我不明白如何在Guice中连接它。我试过这个但无济于事:

class DAO{
  Result row;

  DAO(int rowId){
    //opens DB connection and establishes a link
    //to the object in question
    this.row = attachRow(rowId);
  }

  String getMyString(){
    this.row.getData("mystring");
  }

  int getMyInt(){
    this.row.getIntData("myint");
  }
}

interface DAOProviderFactory {
  Provider<DAO> create(int rowId);
}

class DAOProviderFactoryImpl implements DAOProviderFactory {
  @Override
  public Provider<DAO> create(int rowId) {
    return new DAOProviderImpl(rowId);
  }
}

@RequestScoped
class DAOProviderImpl implements Provider<DAO> {
  int rowId;

  public DAOProviderImpl(int rowId) {
    this.rowId = rowId;
  }

  @Override
  public DAO get() {
    //I want this instance to be request-scoped!
    return new DAO(rowId);
  }
}

//Then bind it in the module
bind(DAOProviderFactory.class).to(DAOProviderFactoryImpl.class);

这不起作用,因为调用daoProvider.get()会在每次调用时返回一个新实例(unscoped)。我想这是因为我的DAOProviderImpl对象不是由Guice实际管理的。另一个问题是锅炉板的数量相当多。

如何使用请求范围的提供程序为特定DAO的{​​{1}}实例提供服务?

如果有人能把我放在正确的道路上,我会很高兴!提前谢谢。

1 个答案:

答案 0 :(得分:2)

这里有几个问题。一个是您拥有DAOProviderFactoryDAOProviderFactoryImpl,这需要rowId能够创建DAOProviderImpl,但您永远不会使用它们。我也不确定Guice是如何运行它的,因为@Inject的构造函数上没有DAO,因为这里没有任何实际的自定义DAO提供程序

无论如何,我认为你可以在这里做一些更简单的事情。只需像这样DAOFactory

@RequestScoped
public class DAOFactory {
  private final Map<Integer, DAO> daos = new HashMap<Integer, DAO>();

  public DAO getDao(int rowId) {
    DAO dao = daos.get(rowId);
    if (dao == null) {
      dao = new DAO(rowId);
      daos.put(rowId, dao);
    }
    return dao;
  }
}

如果你愿意,它当然可以实现一些界面。如果出于某种原因,您不知道rowId在您检索DAO的每个位置,那么您可以首先通过设置rowId来初始化工厂。然后让它只返回在别处创建的DAO

无论如何,您可以在Provider<DAOFactory>或任何地方注入WebPage(请求作用域)。

所有这一切,我不禁想到可能会有更好的整体设计,但不知道更多,我不确定那是什么。