欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-03-09 18:47:20
...

请尊重成果,如需转载请注明来源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/