对于Web应用程序来使用注入另一个bean类的bean,bean需要能够在用户与应用程序交互的持续时间内保持状态。 定义这个状态的方法是给bean一个范围。 您可以给对象表23-1中描述的任何范围,具体取决于您如何使用它。
表23-1 范围
范围 | 注释 | 持续时间 |
---|---|---|
Request | @RequestScoped | 用户在单个HTTP请求中与Web应用程序的交互。 |
Session | @SessionScoped | 用户通过多个HTTP请求与Web应用程序进行交互。 |
Application | @ApplicationScoped | 所有用户与Web应用程序的交互共享状态。 |
Dependent | @Dependent | 默认范围如果没有指定; 这意味着存在一个对象,仅仅服务于一个客户端(bean),并且具有与该客户机(bean)相同的生命周期。 |
Conversation | @ConversationScoped | 用户与servlet的交互,包括JavaServer Faces应用程序。 会话范围存在于开发人员控制的边界内,将跨越多个请求延伸到长时间运行的会话中。 所有长时间运行的会话都被限定到特定的HTTP servlet会话,并且可能不会跨越会话边界。 |
前三个范围由JSR 346和JavaServer Faces规范定义。最后两个由JSR 346定义。
除@Dependent之外的所有预定义范围都是上下文范围。 CDI将上下文范围的bean放置在其生命周期由Java EE规范定义的上下文中。例如,会话上下文及其bean在HTTP会话的生存期内存在。注入bean的引用是上下文感知的。引用始终适用于与正在引用的线程的上下文相关联的bean。 CDI容器确保在由为这些对象指定的范围确定的正确时间创建和注入对象。
您还可以定义和实现自定义作用域,但这是一个高级主题。自定义范围可能被那些实现和扩展CDI规范的用户使用。
范围为对象提供了明确定义的生命周期环境。范围对象可以在需要时自动创建,并在其创建的上下文结束时自动销毁。此外,其状态由在相同上下文中执行的任何客户端自动共享。
Java EE组件(如servlet和企业bean)以及JavaBeans组件不具有明确定义的范围。这些组件是以下之一:
单例,如Enterprise JavaBeans单例Bean,其状态在所有客户端之间共享
无状态对象,如servlet和无状态会话bean,不包含客户机可见状态
必须由其客户端明确创建和销毁的对象,例如JavaBeans组件和有状态会话bean,其状态由客户端之间的显式引用传递共享
但是,如果您创建一个受管Bean的Java EE组件,则它将成为一个作用域对象,该对象存在于一个定义明确的生命周期环境中。
Printer bean的Web应用程序将使用一个简单的请求和响应机制,因此可以如下注释受管Bean:
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
@RequestScoped
public class Printer {
@Inject @Informal Greeting greeting;
...
}
使用会话,应用程序或会话范围的Bean必须是可序列化的,但是使用请求范围的bean不必是可序列化的。