CDI @RequestScoped Bean生命周期 [英] CDI @RequestScoped bean lifecycle

查看:89
本文介绍了CDI @RequestScoped Bean生命周期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我定义了一个带有CDI注释的RequestScoped bean,如下所示.我有几个使用相同bean的页面.当我从一页导航到另一页时.Bean obj保持不变.即使更改会话(使用其他用户登录).Bean对象未更改.

根据RequestScoped定义,应为每个新请求重新创建Bean实例.我错过了什么吗?

我正在使用JSF/Primefaces.导航到detail.xhtml页面后,可以看到从create.xhtml页面输入的值.在备用Bean中,该值不会重新分配.

谢谢

============================================================

import javax.enterprise.context.RequestScoped;

import javax.inject.Named;

@Named("targetManager")

@RequestScoped

公共类TargetManager实现可序列化的{}

===================================>

create.xhtml:

 < ui:composition xmlns ="http://www.w3.org/1999/xhtml"xmlns:ui ="http://java.sun.com/jsf/facelets"xmlns:h ="http://java.sun.com/jsf/html"xmlns:p ="http://primefaces.org/ui"xmlns:f ="http://java.sun.com/jsf/core"template ="../../templates/rapm.xhtml">< ui:define name ="contents">< h:form id ="createform">< h:outputLabel id ="englishNameLabel">< h:outputText id ="englishName" value =#{msg ['view.label.englishname']}:"/>< h:outputText id ="englishNameStar" value ="*" styleClass ="mandatory"/></h:outputLabel>< p:inputText id ="englishTitle" value =#{targetManager.selectedTarget.englishName}">< f:validator id ="englishNameValidate1" validatorId ="duplicateValidator"/></p:inputText>` 

===================================>

detail.xhtml:

 < ui:composition xmlns ="http://www.w3.org/1999/xhtml"xmlns:ui ="http://java.sun.com/jsf/facelets"xmlns:h ="http://java.sun.com/jsf/html"xmlns:p ="http://primefaces.org/ui"xmlns:f ="http://java.sun.com/jsf/core"template ="../../templates/rapm.xhtml">< ui:define name ="contents">< p:scrollPanel id ="scrollPanel" styleClass ="contentPanel ntb" mode ="native">< h:outputText id ="englishName" value =#{msg ['.view.label.englishname']}:"/>< h:outputText id ="englishNameValue" value =#{targetManager.selectedTarget.englishName}"/> 

`

解决方案

CDI确实会为每个请求创建一个新对象,但不会为您的servlet或您正在使用的对象创建一个新对象.

假设您有一个servlet,那么该servlet实例仅创建一次,并且如果您将请求范围的Bean注入该Servlet中,则CDI将无法在Servlet中交换该Bean实例,因为这可能导致不可预测的状态.因此,CDI为该Servlet创建一个代理实例,该代理实例在Servlet生存的所有时间都保持不变.这就是为什么只获取bean实例的单个ID,却只获取CDI代理对象而不是基础bean的ID的原因.当收到新请求时,CDI将创建一个新的bean实例,并为此特定请求使用该bean支持代理.

I defined a RequestScoped bean as below with CDI annotation. I have several pages which use the same bean. When I navigate from page to page. The bean obj keeps the same. Even when I change the session (login wth different user). The bean object is not changed.

According to RequestScoped definition, the bean instance should re-create for each new request. Anything I missed?

I am using JSF/Primefaces. The value input from create.xhtml page can be seen after navigating to detail.xhtml page. In backing bean, the value is not re-assigned.

Thanks,

Zhang

============================================================

import javax.enterprise.context.RequestScoped;

import javax.inject.Named;

@Named("targetManager")

@RequestScoped

public class TargetManager implements Serializable { }

======================================

create.xhtml:

<ui:composition xmlns="http://www.w3.org/1999/xhtml" 
xmlns:ui="http://java.sun.com/jsf/facelets" 
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui" 
xmlns:f="http://java.sun.com/jsf/core" 
      template="../../templates/rapm.xhtml">

<ui:define name="contents">

<h:form id="createform">
  <h:outputLabel id="englishNameLabel">
     <h:outputText id="englishName" value="#{msg['view.label.englishname']}:" />
     <h:outputText id="englishNameStar" value="* " styleClass="mandatory" />
  </h:outputLabel>  
  <p:inputText id="englishTitle" value="#{targetManager.selectedTarget.englishName}" >
    <f:validator id="englishNameValidate1" validatorId="duplicateValidator" />
  </p:inputText>`

======================================

detail.xhtml:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:p="http://primefaces.org/ui"
  xmlns:f="http://java.sun.com/jsf/core"
  template="../../templates/rapm.xhtml">

  <ui:define name="contents">

  <p:scrollPanel id="scrollPanel" styleClass="contentPanel ntb" mode="native">

     <h:outputText id="englishName" value="#{msg['.view.label.englishname']}:"/>
       <h:outputText id="englishNameValue" value="#{targetManager.selectedTarget.englishName}" />

`

解决方案

CDI indeed creates a new object for each request but not for your servlet or what you are using.

Assuming you have a servlet, then the servlet instance is created only once and if you inject a request scoped bean into this servlet, then CDI is not able to exchange the bean instance within the servlet since this could result in unpredictable states. Thus CDI creates a proxy instance for the servlet which remains the same all the time the servlet lives. This is why you get only this single id for the bean instance, you are retrieving the id of the CDI proxy object, not of the underlying bean. When a new request comes in, CDI creates a new bean instance and backs the proxy with this bean for this specific request.

这篇关于CDI @RequestScoped Bean生命周期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆