把容器中的对象绑定到某个范围(Scope)上并不是 CDI 的首创,为了更好地了解 CDI 的范围,我们可以和 Spring IoC 的范围进行对比。
Spring IoC Scope 和 CDI Scope
Spring IoC 为 Bean 对象提供了五个范围,如表 1 所示:
表 1. Spring IoC 中的 Bean Scope
Scope |
说明 |
singleton |
第一次请求时创建,整个 Spring IoC 容器中只会有唯一的对象。对象的生命周期会一直持续到容器销毁。 |
prototype |
每次请求都会创建新的对象。创建后其生命周期脱离 Spring IoC 容器的管理,而由 JVM 当作普通对象来管理。 |
request |
每个 HTTP 请求都会创建新的对象。对象的生命周期取决于 HTTP 请求。 |
session |
每个 HTTP Session 会创建新的对象。对象的生命周期取决于 HTTP Session。 |
global-session |
用于 portlet,这里不作讨论。 |
再来看 CDI 定义的 Scope,如表 2 所示。
表 2. CDI Scope
Scope |
说明 |
RequestScoped |
每个 HTTP 请求都会创建新的对象。对象的生命周期取决于 HTTP 请求。 |
SessionScoped |
每个 HTTP Session 会创建新的对象。对象的生命周期取决于 HTTP Session。 |
ConversationScoped |
每个 Conversation 会创建新的对象。对象的生命周期取决于 Conversation 的创建和销毁。 |
AppliactionScoped |
每个 Web 应用会创建新的对象。对象的生命周期取决于 Web 应用的启动和关闭。 |
Dependent |
对象的生命周期依赖于被注入对象的生命周期。每次请求会创建新的对象。 |
从表 1 和表 2 的对比来看,对方都提供了 Request Scope 和 Session Scope,功能基本相同。
在 Web 应用的层面来看,CDI 的 ApplicationScoped 起到的作用类似于 Spring IoC 的 singleton。
CDI 的 Dependent 在创建对象的行为特点上与 Spring IoC 中的 prototype 比较相似,对象创建后的生命周期的管理,两者却完全不同。
另外,Spring IoC 中没有 Conversation,但 CDI 1.0 规范中明确指出:Conversation 的实现由第三方 Web Framework 来提供。事实上,不使用 JSF 的环境中可能无法使用 Conversation,更详细的信息可在参考资源中找到相关链接。
在容器的实现方式上, Spring IoC 和 CDI 很不一样。Spring IoC 的 Scope 可看作是管理容器对象的特殊手段,而 CDI 则是针对每个 Scope 创建相应的容器。
Normal Scope 和 Pseudo Scope
CDI 的五种 Scope 可分为两个类别,前四种 Scope(Request、Session、Conversation、Application)称为标准 Scope(Normal Scope),Dependent 则属于另一类——伪 Scope(Pseudo Scope)。 CDI 规范规定:
如果在同一线程的不同注入点上,注入相同 Bean 类型的 Normal Scope 对象,那么这些不同注入点所注入的对象是同一实例。Pseudo Scope 中的对象每次注入都会是新构建的对象,没有任何两个注入点会得到同一实例。
原文
http://www.ibm.com/developerworks/cn/java/j-lo-cdijpa/