SeamFramework.orgCommunity Documentation
我们已经看到Web Bean的依赖注入模型如何让我们在部署时期 重载 一个API实现。例如,下面的企业级Web Bean在生产环境下使提供一个PaymentProcessor
接口的实现:
@CreditCard @Stateless
public class CreditCardPaymentProcessor
implements PaymentProcessor {
...
}
但在我们的阶段开发环境中,我们可以使用一个不同的Web Bean来重载这个PaymentProcessor
实现:
@CreditCard @Stateless @Staging
public class StagingCreditCardPaymentProcessor
implements PaymentProcessor {
...
}
我们试图做的是在特定的系统部署环境中使用StagingCreditCardPaymentProcessor
来完全替代AsyncPaymentProcessor
。在这个部署中,部署类型为@Staging
的将有比默认部署类型@Production
更高的优先级,因此下面注入点的客户:
@CreditCard PaymentProcessor ccpp
将会收到一个 StagingCreditCardPaymentProcessor
的实例。
不幸的是,我们很容易掉入几个陷阱:
更高优先级的Web Bean可能没有实现其要重载的所有的API类型,
更高优先级的Web Bean可能没有声明其要重载的所有绑定类型,
更高优先级的Web Bean可能没有和其要重载的Web Bean拥有相同的名字,或者
其要重载的Web Bean有可能声明了一个生产者方法,清除方法或者观察者方法。
在上面的任何一种情况,我们试图重载的Web Bean仍旧可以在运行时被调用。因此重载对于开发者来说是很容易出错的。
Web Bean提供了一个特殊的特性,称之为特化,能够帮助开发者避免这些陷阱。特化初看起来有些神秘,但是在实际应用中非常容易使用,你很快就会感激它提供的特殊的安全性。
特化是为简单和企业级Web Bean提供的特性。要使用特化,更高优先级的Web Bean必须:
是其重载的Web Bean的直接子类,并且
如果其重载的是简单的Web Bean, 它也要是一个简单的Web Bean;如果其重载的是企业级的Web Bean, 它也要是一个企业级的Web Bean,并且
需要使用 @Specializes
注释。
@Stateless @Staging @Specializes
public class StagingCreditCardPaymentProcessor
extends CreditCardPaymentProcessor {
...
}
我们称更高优先级的Web Bean特化了它的超类。
当使用特化时:
超类的绑定类型自动被使用@Specializes
注释的Web Bean继承,并且
超类的Web Bean名称自动被使用@Specializes
注释的Web Bean继承,并且
超类声明的生产者方法,清除方法和观察者方法将在使用@Specializes
注释的Web Bean实例上调用。
在我们这个例子中,CreditCardPaymentProcessor
的绑定类型 @CreditCard
被StagingCreditCardPaymentProcessor
继承。
进一步,Web Bean管理器将验证:
超类的所有API类型是使用 @Specializes
注释的Web Bean的API类型(所有企业级Bean超类的本地接口是子类的本地接口)
使用 @Specializes
注释的Web Bean的部署类型比超类的部署类型拥有更高的优先级,并且
没有其他特化该超类的Web Bean被激活。
如果任何一条有冲突的话,Web Bean管理器将在初始化时抛出一个异常。
因此,我们可以确定当使用@Specializes
注释的Web Bean被部署和激活时,超类在系统的任何部署中都不会被调用。