范围类型如何影响EntityQuery对象的重用方式

时间:2010-07-03 04:15:18

标签: seam

for (...) {
    UserList userList = (UserList) Component.getInstance(UserList.class, ScopeType.METHOD);
    userList.getUserByEmailAddress(emailId);
}

Seam支持不同的ScopeType(例如METHOD,PAGE,EVENT,APPLICATION)。我们目前使用METHOD范围通过电子邮件ID检索User对象。上述代码存在于for循环中(即,对于我们检索用户对象的用户电子邮件地址的集合)。这是正确的ScopeType还是最好将UserList声明移到for循环

之上

我们在某些范围类型中观察到userList对象被重用,有人可以澄清它是如何工作的。在seam中是否有任何工具可以帮助你理解这些对象如何被重用(我们打开了一些跟踪日志记录,但是有太多的调用正在进行并且不太清楚)

1 个答案:

答案 0 :(得分:1)

ScopeType.METHOD说

  

对会话bean或JavaBean组件的每次调用都会将新方法上下文放入与当前线程关联的方法上下文堆栈中。方法返回时会破坏上下文。

Seam的许多功能都是作为一组内置的Seam拦截器实现的。这里有一段MethodContextInterceptor(内置Seam拦截器)的代码,其中API表示

  

设置METHOD上下文并在调用期间取消SFSB的攻击

MethodContextInterceptor.java请参阅下面的评论并与上面突出显示的文本进行比较

@AroundInvoke
public Object aroundInvoke(InvocationContext ctx) throws Exception {
    Component comp = getComponent();

    String name = comp.getName();
    Object target = ctx.getTarget();
    Method method = ctx.getMethod();
    Object[] parameters = ctx.getParameters();

    /**
      * beginMethod
      *
      * Takes care of putting a NEW method context onto the stack of method contexts
      */
    Context outerMethodContext = Lifecycle.beginMethod();

    try {
        Contexts.getMethodContext().set(name, target);
        Contexts.getMethodContext().set("org.jboss.seam.this", target);
        Contexts.getMethodContext().set("org.jboss.seam.method", method);
        Contexts.getMethodContext().set("org.jboss.seam.parameters", parameters);
        Contexts.getMethodContext().set("org.jboss.seam.component", comp);

        /**
          * And after method return 
          */ 
        return ctx.proceed();
    } finally {
        /**
          * endMethod Takes care of destroying The previous added method context
          */       
        Lifecycle.endMethod(outerMethodContext);
    }
}

如您所见,我没有看到ScopeType.METHOD提供任何特殊行为。我认为Seam项目的创始人Gavin King创建了ScopeType.METHOD作为可以在后面使用的附加范围。甚至Seam in Action一书也没有涵盖ScopeType.METHOD范围。

因此,每次调用 getUserByEmailAddress 时,都会执行上述例程。关于上下文,Seam in Action书很清楚

  

上下文定义了可以找到变量名称的位置以及它挂起的时间

所以你想要的范围应该吸引你的商业需求。

关于EntityQuery ???这就是Seam in Action书中所说的

  

如果每次需要显示结果时都执行查询,则在数据库中放置压力 。在另一个极端,如果您坚持使用的时间过长,您最终会向用户提供可能会让他们感到困惑的过时信息,或者更糟糕的是,导致他们犯错决定。

默认情况下,某些Query方法通过在类的私有属性中缓存结果来避免冗余数据库查询。但是,因为你改变了

,它可以被覆盖
  • 查询限制参数
  • 排序顺序
  • 最大结果值
  • 第一个结果偏移
  • 通过调用refresh()
  • 手动清除结果

当您更新某些@Entity并且需要刷新存储的结果集时,最后一项非常有用。您可以使用Seam事件来完成它。但如果您总是想要一个新的结果集,请将您的EntityQuery设置为ScopeType.EVENT,然后在for循环之前使用它

UserList userList = (UserList) Component.getInstance(UserList.class, ScopeType.EVENT);
for (...) {
    userList.getUserByEmailAddress(emailId);
}

这里是Seam和Spring范围之间的并排比较

Seam                               Spring            Suited for
ScopeType.STATELESS                singleton         Service, repositories, Thread-safe components
ScopeType.APPLICATION              singleton         Service, repositories, Thread-safe components
ScopeType.SESSION                  session           User login
ScopeType.CONVERSATION             -                 Page flow
ScopeType.PAGE                     -                 Server-side based component model
ScopeType.EVENT                    request           Non Thread-safe components

注意ScopeType.CONVERSATION不等于Spring Web流。 Seam ScopeType.CONVERSATION超越了Web层。甚至持久化上下文也可以包含在对话上下文中。请记住,当您拥有基于服务器端的组件模型框架(如JSF,Wicket等)时,ScopeType.PAGE是有意义的...通常,当您具有完全Java EE环境和ScopeType.APPLICATION时,将使用ScopeType.STATELESS。您使用普通的POJO而不是EJB。