我的问题是,如何使用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框架的一部分,它将所有页面对象保持在会话中。在每个请求getMyString
和getMyInt
方法被多次调用以获取值之后,在页面上向用户显示它们之前。假设DAO
对象附加到表中的一个特定行,只是从该行中提取数据。
出于性能原因,我需要daoProvider
始终返回相同的实例,以避免每次调用getMyString
或getMyInt
时重新连接到数据库。另一方面,实例必须跨请求进行更新,以便在页面刷新后对用户显示对数据库的任何更新。
所以我要找的是会话范围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}}实例提供服务?
如果有人能把我放在正确的道路上,我会很高兴!提前谢谢。
答案 0 :(得分:2)
这里有几个问题。一个是您拥有DAOProviderFactory
和DAOProviderFactoryImpl
,这需要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
(请求作用域)。
所有这一切,我不禁想到可能会有更好的整体设计,但不知道更多,我不确定那是什么。