2015-10-19 91 views
2

我試着去了解一個JSF示例出書的Java EE7發展與Wildfly的,但這裏是我不明白 - 即使它的工作原理:@Produces在成員變量

豆:

@Named 
@RequestScoped 
public class TheatreSetupService { 
    ... 
    @Produces 
    @Named 
    private SeatType newSeatType; 

    @PostConstruct 
    public void initNewSeatType() { 
     newSeatType = new SeatType(); 
    } 
    .... 
} 

XHTML:

<h:form id="reg" role="form"> 
    <div class="form-group has-feedback #{!desc.valid? 'has-error' : ''}"> 
     <h:outputLabel for="desc" value="Description" 
         styleClass="control-label"/> 
     <h:inputText id="desc" value="#{newSeatType.description}" 
         p:placeholder="Enter a description here" class="form-control" 
         binding="#{desc}"/> 
     <span class="#{!desc.valid ? 'glyphicon glyphicon-remove form-control-feedback' : ''}"/> 
     <h:message for="desc" errorClass="control-label has-error"/> 
    </div> 
</h:form> 

實體:

@Entity 
@Table(name = "seat_type") 
public class SeatType implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    @NotNull 
    @Size(min = 1, max = 25, message = "Enter a Seat Description (max 25 char)") 
    @Pattern(regexp = "[A-Za-z ]*", message = "Description must contain only letters and spaces") 
    private String description; 

    private SeatPosition position; 

    @NotNull 
    private Integer price; 

    @NotNull 
    private Integer quantity; 

    @OneToMany(mappedBy = "seatType", fetch = FetchType.EAGER) 
    private List<Seat> seats; 

    public SeatType() { 
     // empty for jpa 
    } 

    ... 

} 

我不明白@Produces對成員變量newSeatType的影響。創建由TheatreSetupService類明確管理。對我來說,它看起來就像是一個導出,該成員可用於jsf,但@Named註釋不足以使此示例正常工作。任何人都可以解釋我在這個小例子中發生了什麼?據我看,這不是很常用 - 這是真的嗎?

謝謝你的提示!

Dominic

回答

1

這比JSF特有的更具CDI特定性。

@Named註釋是在CDI中引入的,它被設計爲針對相同類型的不同bean注入的by-name-distinguished限定符。它也被設計用於取代以前的JSF管理的豆註釋爲@ManagedBean(如果在標準servlet容器(如未安裝CDI的Tomcat)上運行,則@ManagedBean仍然是唯一的解決方案)。因此,註釋爲@Named註釋的一個bean是CDI管理的bean,可以通過@Inject註釋將其注入代碼中的任何位置,也可以通過EL解析器的名稱(如#{named-bean-name})解析。

要成爲一個支持CDI的bean,一個類必須有一個默認構造函數,這是CDI爲了創建類的一個實例而隱式使用的。在某些情況下(例如,如果類沒有默認構造函數,或者因爲構造函數的可見性受限,或者需要預初始化一個bean的實例),創建bean實例的唯一方法是生產方法或字段,它們分別是曾經是一個bean實例創建源。

@Produces -annotated方法或字段被設計爲充當注射對象的來源。因此,爲了創建像一個bean的實例:

public class SeatType { 

    public SeatType(Object obj) {} 
} 

我們需要提供一個製作方法:

public class SeatTypeFactory { 

    @Produces 
    public SeatType createSeatType() { 
     return new SeatType(new Object()); 
    } 
} 

或生產領域:

public class SeatTypeFactory { 

    @Produces 
    private SeatType seatType = new SeatType(new Object()); 
} 

到目前爲止,你可以通過注入@Inject註釋在代碼中使用它,但尚未在EL中使用它。在EL得到解決,需要在生產領域或生產方法指定@Named註釋:只用你的SeatType@Named註釋(該

@Produces 
@Named 
private SeatType newSeatType = new SeatType(new Object()); 

@Produces 
@Named("newSeatType") 
public SeatType createSeatType() { 
    return new SeatType(new Object()); 
} 

在你的情況下,可以實現幾乎相同,不同的是,豆類的情況下,通過@Produces創建的,不是管理本身並不能包含其他注入點):

@Entity 
@Table(name = "seat_type") 
@Named("newSeatType") 
@RequestScoped 
public class SeatType implements Serializable { 
    ... 
} 
1

在這個例子中,筆者也許是過度使用CDI。你可以簡單地聲明並創建SeatType豆和往常一樣:

private SeatType newSeatType = new SeatType(); 

,並通過backging豆在你的頁面訪問這個bean:

<h:inputText id="desc" value="#{theatreSetupService.newSeatType.description}" 

您必須創建newSeatType屬性getter和setter。

編輯:

在另一方面,@Produces註釋只是表明你將能夠從應用程序的任何其他CDI豆注入這個bean,並注入豆將通過newSeatType被檢索TheatreSetupService CDI bean的屬性。但是如果你想通過EL從JSF頁面的任何一點注入它,你需要一個qualyfier來消除注入點的歧義。

如果您需要從應用程序中的其他幾個bean注入此具體bean,則不會過度使用。 在這種情況下,您必須創建一個限定符來區分您的混凝土豆和全新豆。例如:

限定符:

@Qualifier 
@Retention(RUNTIME) 
@Target({TYPE, METHOD, PARAMETER, FIELD}) 
public @interface TheSpecialSeatType{} 

生產者:

@Produces 
@Named 
@TheSpecialSeatType 
private SeatType newSeatType; 

使用您的具體座A型輔助類:

public class HelperBean{ 
    // this bean will be the one created inside the backing bean 
    @Inject 
    @TheSpecialSeatType 
    private SeatType theSeatType; 
    ... 
} 

新增:

如果您想直接從您的頁面訪問屬性(如示例中所示),那麼您將需要CDI文檔中所述的@Named和@Produces註釋。 @Produces通過@Inject註釋將生成的bean公開給其他Bean,並通過EL公開給JSF頁面。

然後,如果你只想在其他bean內部注入,只能使用@Produces。如果你想在JSF頁面內部注入@Produces和@Named。