【问题标题】:@ManagedProperty - Inject one request scoped bean into another request scoped bean@ManagedProperty - 将一个请求范围的 bean 注入另一个请求范围的 bean
【发布时间】:2011-04-13 11:17:59
【问题描述】:

我有这个 SearchBean

@ManagedBean(name = "searchBean")
@RequestScoped
public class SearchBean implements Serializable
{
    private String input = null;

    // getter methods
    public String getInput() {
        return input;
    }

    // setter method
    public void setInput(String input) {
        this.input = input;
    }

    public String Submit() {
        return null;
    }    
}

我可以使用@ManagedProperty 将它注入到另一个bean 中吗?例如:

@ManagedBean(name = "bookBean")
@RequestScoped
public class BookBean implements Serializable
{
    @ManagedProperty(value = "#{searchBean}")
    private SearchBean searchBean;  

    @PostConstruct
    public void init()
    {   
       System.out.println("Value: " + searchBean.getInput());
    }

    public SearchBean getSearchBean() {
       return searchBean;
    }

    public void setSearchBean(SearchBean searchBean) {
       this.searchBean = searchBean;
    }   
}

还有 Facelet (search.xhtml):

<h:form id="formSearch">
   <h:commandButton value="Search" action="#{searchBean.Submit}" />
</h:form>

更新:我通过ui:insert 组件将search.xhtml 插入到book.xhtml 中,如下所示:

<h:form id="formBooks">
   <ui:insert name="search">
      <ui:include src="/templates/common/search.xhtml"/>
   </ui:insert> 
</h:form>

上面的searchBean.getInput() 方法应该返回一个值作为表单提交的结果。上面的注入方法可以吗?

【问题讨论】:

  • @user:我删除了我的答案,因为如果托管属性注入有效(这显然是“是”),那只会回答你的 initial 问题,但 McDowell 做得更好回答您的真正问题的工作(在调用@PostConstruct 时属性为空。
  • @BalusC:当您的答案在刷新后消失时,我认为我的浏览器有问题。是的,对此感到抱歉。我仍在尝试通过实际示例来了解规格,但有时我会卡住,不知道如何前进。不过,感谢您的回答。

标签: jsf jsf-2 code-injection


【解决方案1】:

我假设SearchBean.input 将绑定到input field

public class SearchBean implements Serializable {
    private String input = null;

类似这样的:

<h:inputText value="#{searchBean.input}" />

如果是这样,那么这将为空:

@PostConstruct
public void init()
{   
   System.out.println("Value: " + searchBean.getInput());
}

但是,假设已经设置了一个值,那么调用这个方法时它不会为null:

public String Submit() {
    return null;
}

图片来自 Richard Hightower 的JSF for nonbelievers: The JSF application lifecycle

原因在于 JSF 生命周期的工作方式:

  1. #{searchBean...}第一次被解析发现不存在时:
    • bean 已实例化
    • 执行任何依赖注入(在这种情况下没有)
    • @PostConstruct 方法被调用
    • bean 被放入作用域
  2. 假设应用请求值和验证阶段成功,SearchBean.setInput(String) 在更新模型值阶段被调用
  3. SearchBean.Submit() 在 Invoke Application 阶段被调用

这个过程在JSF specification中定义。


现在,如果SearchBean.input 是直接从参数映射中注入的,那么在@PostConstruct 期间它不会为空:

@ManagedProperty(value = "#{param.someParamName}")
private String input;

但是,这样做并没有任何真正的优势 - 您正在跳过任何输入验证,并且您不能使用 SearchBean.input 作为字段绑定,因为它将在更新模型值阶段被覆盖。

SearchBean.Submit() 方法是执行搜索的应用程序逻辑所在。

【讨论】:

  • @McDowell:规范的那部分对我来说仍然有点模糊,所以我想我做一个实际的例子来看看它是如何工作的。你是对的:我将searchBean#input 绑定到h:inputText,根据你的解释,返回的值将为空 - 这解释了为什么我在提交表单时返回了空。您能否解释一下 - 也许用一些代码示例 - 如何在 SearchBean.Submit() 方法中设置值。我不明白这部分。
  • 如果将输入字段绑定到SearchBean,将其作为托管属性注入BookBean,并将命令按钮绑定到BookBean,则搜索bean和输入值将在那里。 postconstruct 在 bean 的构造和依赖注入之后直接调用,但在输入值设置之前。
  • @user463053 - 输入控件将在更新模型值期间设置SearchBean.input;在 Invoke Application 期间调用 Submit() 方法时,您可以只引用 this.input
  • @BalusC: 你的意思是@ManagedProperty(value = "#{param.input}") private String inputBookBean 类中,然后在某些数据库方法中使用input
  • 那是另一种方式。我的意思是将动作方法submit()放在BookBean中,让命令按钮指向它,最后在该动作方法中完成数据库工作。
猜你喜欢
  • 1970-01-01
  • 2013-08-26
  • 2015-08-16
  • 1970-01-01
  • 2011-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多