7.7. Bean 生命周期
此任务显示如何在请求的生命周期内保存 Bean。
注入 Bean 的默认范围为 @Dependent
。这意味着 Bean 的生命周期取决于拥有该参考的 Bean 的生命周期。还有其他一些范围,您可以定义自己的范围。如需更多信息,请参阅上下文和范围。
管理 Bean 生命周期
使用所需范围给 Bean 标注。
@RequestScoped @Named("greeter") public class GreeterBean { private Welcome welcome; private String city; // getter & setter not shown @Inject void init(Welcome welcome) { this.welcome = welcome; } public void welcomeVisitors() { System.out.println(welcome.buildPhrase(city)); } }
在 JSF 视图中使用 Bean 时,它会保留状态。
<h:form> <h:inputText value="#{greeter.city}"/> <h:commandButton value="Welcome visitors" action="#{greeter.welcomeVisitors}"/> </h:form>
您的 bean 保存在与您指定的范围相关的上下文中,只要适用范围,则会持续。
7.7.1. 使用 Producer 方法
制作者方法是一种充当 bean 实例来源的方法。如果指定的上下文中没有实例,方法声明本身会描述 bean,容器调用获取 bean 实例的方法。制作者方法使应用可以完全控制 bean 实例化流程。
本节介绍如何使用制作者方法生成各种不是注入 Bean 的不同对象。
示例:使用 Producer 方法
通过使用制作者方法而非替代方案,部署后允许多形性。
示例中的 @Preferred
注释是限定符注释。有关限定符的更多信息,请参阅质量。
@SessionScoped public class Preferences implements Serializable { private PaymentStrategyType paymentStrategy; ... @Produces @Preferred public PaymentStrategy getPaymentStrategy() { switch (paymentStrategy) { case CREDIT_CARD: return new CreditCardPaymentStrategy(); case CHECK: return new CheckPaymentStrategy(); default: return null; } } }
以下注入点具有与 producer 方法相同的类型和限定注释,因此它会使用常见的上下文和依赖注入规则解析为制作者方法。容器调用制作者方法来获取实例来为这个注入点提供服务。
@Inject @Preferred PaymentStrategy paymentStrategy;
示例:将范围分配给一个 Producer 方法
制作者方法的默认范围为 @Dependent
。如果您将范围分配给 Bean,它将绑定到适当的上下文。本例中的 producer 方法每个会话仅调用一次。
@Produces @Preferred @SessionScoped public PaymentStrategy getPaymentStrategy() { ... }
示例:在 Producer 方法中使用 Injection
应用程序直接实例化的对象无法利用依赖项注入,也没有拦截器。但是,您可以使用依赖项注入制作者方法来获取 bean 实例。
@Produces @Preferred @SessionScoped public PaymentStrategy getPaymentStrategy(CreditCardPaymentStrategy ccps, CheckPaymentStrategy cps ) { switch (paymentStrategy) { case CREDIT_CARD: return ccps; case CHEQUE: return cps; default: return null; } }
如果您将请求作用域 Bean 注入会话范围制作者中,则制作者方法会将当前的请求作用范围实例提升到会话范围中。这几乎肯定不是所需的行为,因此,以这种方式使用制作者方法时要谨慎。
producer 方法的范围不继承自声明制作者方法的 bean。
借助制作者方法,您可以注入非 Bean 对象并动态更改代码。