如何为数据对象创建范围化的 Guice 提供者?
我的问题是,如何对数据对象使用 guice 提供者的强大功能(它们确定实例范围的能力)?
基本原理如下:我有一个会话范围的类 WebPage
,它根据 Web 请求从数据库对象 DAO
获取数据。
//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
时重新连接到数据库。另一方面,必须跨请求更新实例,以便在页面刷新后用户可以看到对数据库的任何更新。
因此,我正在寻找的是会话范围的 WebPage 对象内的请求范围的 DAO 提供程序。问题是我不明白如何在 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()
每次调用都会返回一个新实例(无作用域)。我猜这是因为我的 DAOProviderImpl 对象实际上并不是由 Guice 管理的。另一个问题是大量的样板文件。
如何使用请求范围的提供程序为具有特定 rowId
的 DAO
实例提供服务?
如果有人能让我走上正确的道路,我将不胜感激!提前致谢。
My question is, how do I use the power of guice providers (their ability to scope instances), for data objects?
Here is the rationale: I have a session-scoped class WebPage
that fetches data upon a web request from a database object DAO
.
//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();
}
}
The WebPage
object is part of a web framework which keeps all page objects in session. Upon each request getMyString
and getMyInt
methods are called several times to fetch values before displaying them to the user on the page. Assume that DAO
object is attached to one particular row in a table and just fetches data from that row.
For performance reasons, I need daoProvider
to always return the same instance, to avoid reconnection to the database every time getMyString
or getMyInt
is called. On the other hand, the instance has to be renewed across requests, to make any updates to the database visible to users after page refresh.
So what I am looking for is a request-scoped provider of DAO
inside a session-scoped WebPage
object. The problem is I don't understand how to wire it up in Guice. I have tried this but to no avail:
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);
This did not work, as calling daoProvider.get()
would return a new instance (unscoped) every call. I guess the reason for this is that my DAOProviderImpl
object is not acually managed by Guice. Another problem is the fair amount of boiler-plate.
How can I serve an instance of DAO
with a particular rowId
using a request-scoped provider?
If anyone could put me on the correct path, I'd be greatful! Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里有几个问题。一是您有这个
DAOProviderFactory
和DAOProviderFactoryImpl
,它们需要rowId
才能创建DAOProviderImpl
,但你从不使用它们。我也不确定 Guice 是如何运行这个的,因为DAO
的构造函数上没有@Inject
,而且你没有任何实际的自定义< code>DAO 提供者绑定在此处。无论如何,我认为你可以在这里做一些更简单的事情。只需创建一个像这样的 DAOFactory :
当然,如果您愿意,它可以实现一些接口。如果由于某种原因您不知道检索
DAO
的每个位置的rowId
,您可以先通过设置来初始化工厂:它的 rowId ,然后让它返回在其他地方创建的 DAO 。不管怎样,您可以在
WebPage
或任何地方注入一个Provider
(请求范围)。综上所述,我不禁认为可能会有一些适合您的更好的整体设计,但由于不知道更多,我不确定那会是什么。
There are a couple problems here. One is that you have this
DAOProviderFactory
andDAOProviderFactoryImpl
, which require arowId
to be able to create aDAOProviderImpl
, but you never make use of them. I'm also not sure how Guice is even running this at all, since there's no@Inject
onDAO
's constructor and since you don't have any actual customDAO
provider bound here.Anyway, I think you can do something simpler here. Just make a
DAOFactory
like this:It could implement some interface of course if you want. If for some reason you don't know the
rowId
in every place you're retrieving theDAO
, you could instead do something where you first have to initialize the factory by setting itsrowId
and then have it just return theDAO
that was created elsewhere.Anyway, you'd then inject a
Provider<DAOFactory>
(request scoped) in yourWebPage
or wherever.All that said, I can't help but think there might be some better overall design for you, but not knowing more I'm not sure what that would be.