【问题标题】:JSF injection with managed property, good pattern?带有托管属性的 JSF 注入,好的模式?
【发布时间】:2012-09-07 14:56:33
【问题描述】:

我对 JSF 很陌生,并没有真正“习惯”不同的想法,所以我在(我认为)是基本的东西上苦苦挣扎。

假设我有一个 User 类,它是一个会话 bean。

假设我有一个包含 10000 个对象的控制器,比如 Factory,它需要能够将其中一些设置为“锁定”,在我们的例子中,这意味着“锁定”字段不再变为 null,而是引用“LockedItem”对象。

这是我无法正常工作的地方:LockedItem,当你实例化它时,它应该引用当前登录的用户。我应该怎么做?

我尝试使用@managedproperty 进行注入,但它在 LockedItem.constructor 中为空(我认为这是正常的)然后我尝试使用 @PostConstruct 方法,但从未调用过该方法(为什么?即使我将其设为 managedbean ... postconstruct 方法是否仅在“.xhtml”创建对象时调用?) 或者我应该使用“java se”技巧,比如让用户静态?


阐明为什么不调用 @PostConstruct 的代码(“Seat”之一):

.xhtml

<h:outputLabel id="user" value="Hello #{user.name}" />
<h:outputLabel id="car" value="you have #{car.brand}" />

用户

package test;

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class User implements Serializable {
    private String name ;

    public User()
    {
        name = "toto"; 
        System.out.println("User constructor");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


}

汽车

package test;

import java.io.Serializable;

import javax.faces.bean.ManagedBean;

@ManagedBean
public class Car implements Serializable {
    private String brand ;
    private Seat seat ;

    public Car()
    {
        brand = "audi" ;
        seat = new Seat();
        System.out.println("Car constructor") ;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }


}

座位

package test;

import java.io.Serializable;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;

@ManagedBean
public class Seat implements Serializable {
    private int nb ;
    private String userName ;

    @ManagedProperty("#{user}")
    private User user ;

    public Seat()
    {
        nb = 4 ;
        userName="na";
        System.out.println("! Seat constructor ") ;
    }

    @PostConstruct
    public void init()
    {
        System.out.println("!! Seat postconstruct : "+user.getName());
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public int getNb() {
        return nb;
    }

    public void setNb(int nb) {
        this.nb = nb;
    }
}

谢谢!

【问题讨论】:

    标签: jsf design-patterns code-injection managed-bean postconstruct


    【解决方案1】:

    @PostConstruct 是正确的方式。

    如果您使用 new 运算符自己实例化 bean,则不会调用它(显然)。仅当 JSF 在 EL 上下文中第一次引用它时实例化和管理 bean 本身时才调用它,例如 #{bean}。这确实通常发生在视图端,但也可能发生在模型/控制器端 @ManagedProperty("#{bean}")Application#evaluateExpressionGet()

    您绝对不应该将User 设为静态。它将在应用程序范围内共享,而不是在会话范围内共享。

    另一种方法是将当前的User 作为LockedItem 的构造函数参数传递,或者调用初始化方法你自己,以确保该类不代表合法的JSF 支持bean完全没有。

    【讨论】:

    • 感谢 BalusC!我已经在一个小测试用例中尝试了所有这些,但似乎仍然无法获得使用 @ManagedProperty 调用的类(“Seat”)的 PostConstruct,您是否碰巧知道我的代码中有什么问题(作为回复发布)? (请注意,如果我有 ,它确实会被调用)
    • 您应该使用@ManagedProperty("#{seat}") 而不是new Seat()
    • 根据您的解决方案,实际上由于抽象,我仍然有一个“模式”问题。在我的具体情况下,我有一个抽象的LibraryObject,它定义了一个锁定对象的默认实现(即关联LockedItem)。 LockedItem 必须知道谁是 User(会话 bean)才能得到它的名字。最初,LibraryObjectLockedItem 都不是 bean。最好的方法似乎是使 LibraryObject 成为一个 managedBean,我在其上注入 User 并且,正如你所说,创建一个新的 LockedItemUser 参考,但我不能因为它的抽象...有什么想法吗?
    猜你喜欢
    • 2015-03-11
    • 2011-12-25
    • 2012-01-27
    • 2012-06-30
    • 1970-01-01
    • 2023-03-27
    • 2013-09-30
    • 1970-01-01
    • 2012-05-19
    相关资源
    最近更新 更多