CDI框架笔记-weld reference中文翻译(三)

请尊重成果,如需转载请注明来源http://equalxx.iteye.com/

 

Chapter 2.More about beans关于bean的更多内容

 

bean一般是包含业务逻辑的应用类。可以直接被java代码调用,也可以在标准的EL表达式中调用。Bean也可以访问事务资源。Bean之间的依赖关系由容器自动管理,大多bean是有状态和上下文的。Bean的生命周期由容器管理。

 

让我们再看一下,到底什么叫“有上下文的”?bean有没有状态关系到我有哪个bean的实例。不像一个没有状态的组件模型(比如无状态会话bean)或是一个单例组件模型(比如servlets或是单例bean),有状态bean在不同的客户端有着不同的状态。是否标识用户可见状态(client-visible state)取决于客户端有没有对这个bean的实例的引用。

 

无状态或单例模型,不同于有状态会话bean,客户端不会通过显式地创建销毁它来控制它的生命周期。取而代之的是用bean scope来决定:

1、每个bean实例的生命周期

2、哪些客户端可以共享对bean的指定实例的引用

 

对于CDI应用的给定线程,可能会有一个通过bean scope关联的活动上下文。这个上下文在这个线程中可能是唯一的(比如这个beanrequest scoped的),或是它也可能同时与其他线程共享(比如这个beansession scoped的),甚至和所有其他线程共享(这用的是application scoped)。

 

执行在同一上下文中的客户端(比如说其他beans)用的都是同一个bean实例。但是在不同上下文中执行的客户端,用的是不同的实例(这取决于上下文之间的关系)。

 

上下文其中一项最大的优点就是它可以让状态beanservice一样。客户端不必去管理它的bean的生命周期,也不用知道bean的生命周期是什么。这些bean都是松耦合的,因为:

1、他们通过明确的公共API来管理相互间关系

2、它们的生命周期跟客户端完全解耦

 

我们可以把一个bean替换成继承同一个接口的另一个bean(这个bean可以有不同的生命周期(scope))而不用影响任何其他bean的实现。事实上,CDI提供了一个简单的方式在部署时重载,我们会在4.7节的“Alternatives”详细介绍。

 

要注意不是所有bean的客户端都是bean本身。其他对象,比如servlets或消息驱动beanmessage-driven beans),他们都不是可注入到其他bean的上下文对象,但他们仍然能够通过注入获取对其他bean的引用。

 

 

2.1. The anatomy of a bean bean的解析

 

在此前我们已经铺垫了这么多,下面我们来正式地介绍bean,根据规范:

一个bean由以下属性组成:

1、一个(非空)bean类型集

2、一个(非空)限定符集

3、一个Scope

4、可选,一个bean EL name

5、一组拦截器绑定

6、一个bean的实现

此外,一个bean可能是alternativ的,也可能不是。

让我们去看看这些属性都是什么意思。

 

2.1.1 Bean typesqualifiers and dependency injection bean类型,限定符和依赖注入

 

Bean通常通过依赖注入获取对其他bean的引用。任何一个被注入的属性规定了一个“合同”,所有要注入的bean必须满足这个“合同”。这个“合同”就是:

1、bean type

2、一组限定符

bean type表明了bean是用户可见类型,它可以是用户定义的class或接口。如果bean是个EJB会话bean,那么它的bean type就是@Local接口,或是bean-class的本地视图。一个bean可能会有很多个bean type。比如说下面的bean有四个bean type

 

public class BookShop
extends Business
implements Shop<Book> {
...
}

 

 

它的bean type BookShopBusinessShop<Book>,以及隐式类型java.lang.Object(注意,参数化类型是合法的bean类型)。

 

同时,下面这个会话bean只有本地的三个接口BookShopAuditablejava.lang.Object可以作为bean type,但由于@StatefulBookShopBean不是用户可见类型。

 

@Stateful
public class BookShopBean
extends Business
implements BookShop, Auditable {
...
}

 

 

注意:会话beanbean type包括本地接口和beanlocal view(如果有的话)。EJB远程接口不被认为是会话beanbean type。你不能把一个EJB通过远程接口注入,除非你定义一个资源,这个会在Chapter 14Java EE组件环境资源中介绍。

 

(译者注:其实这段光看英文感觉难以和实际使用关联起来,bean type到底讲了什么,查看了一些资料以后我认为可能是在说,bean通过可以通过不同的bean type注入,而bean type包含了什么内容,有个网址里面有说明http://moon26.blogspot.jp/2012/01/javaee6-cdi-bean-and-bean-types.html,我会接下来和同事一起讨论,它究竟在开发中处于什么角色,再来更新此部分内容)

 

Bean types可以通过@Typed注解来指定,同时列出所有应该为bean type的类。比如说这个bean types bean已经被限制为Shop<Book>java.lang.Object

 

@Typed(Shop.class)
public class BookShop
extends Business
implements Shop<Book> {
...
}

 

 

有时,仅有bean type的话并不能提供给容器足够的信息去让容器知道该注入哪个bean。举例说,假设我有两个实现了PaymentProcessor接口的实现类:CreditCardPaymentProcessorDebitPaymentProcessor。如果把它俩注入到PaymentProcessor类型的域中,就会引起混淆。在这种情况下,用户必须提供更多的特性来告知容器应该注入哪一个。所以我们通过qualifier来指明特性。

 

一个qualifier是个用户定义的注解,用@Qualifier来定义。它是一个类型系统(type system)的一个扩展。它使我们不用基于名称来区分注入类型。以下就是个用@Qualifier注解的例子:

 

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

 

 

 

你可能还不习惯看到上面这样的创建注解的代码,有可能这是你第一次遇到这样定义。用CDI的话,定义注解将会成为你时不时需要去做的事儿。

 

注意:

请注意在CDIEJB中的注解名称,你会发现他们多是形容词。我们鼓励您在创建自定义注解时候也遵循这种习惯,当它们是用来描述行为和指明类角色的时候。

 

现在我们已经定义了一个特性注解了,我们可以在注入点使用它来明确注入类。下面的注入点包含了bean类型PaymentProcessor以及qualifier @CreditCard

 

@Inject @CreditCard PaymentProcessor paymentProcessor

 

 

注意:

若一个bean或是一个注入点没有被一个qualifier修饰,它会有一个默认修饰符@Default

 

 

这还没结束,CDI还定义了一个简单的解决规则用来帮助容器该接下来怎么做,当多个bean同时满足“合同”的时候。我们会在Chapter 4,依赖注入和程序化查找章节讨论细节。

 

请尊重成果,如需转载请注明来源http://equalxx.iteye.com/

猜你喜欢

转载自equalxx.iteye.com/blog/2353215