2015-10-19 77 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。