Spring--标准化的定位器模式
我一直将服务定位器模式视作良好的J2EE规范的主要组成部分。对于不熟悉这一术语的人来说,可以这样理解它:我们一般认为典型的J2EE应用程序由若干层组成。通常有Web层、服务层(EJB、JMS、WS、WLS控件)以及数据库。一般来说,完成某一请求所需的“查找”服务中都包含了一些方法。Service Locator(服务定位器)模式认为,将这些方法包装在某种隐藏了生成或查找给定服务的复杂性的工厂类中是一个好主意。这减少了JNDI或只会造成Web层操作类混乱的其他服务产品代码的增加。在Spring出现以前,这通常是由经过考验证明可靠的(tried-and-true)Singleton类来实现的。Singleton/Locator/Factory模式可以描绘为:

图2. 定位器模式的顺序图
这是对散布在整个Web控制器代码中的增加的JNDI查找代码的一个巨大改进。它被巧妙地隐藏在工厂内部的协作类中。我们可以使用Spring来改进这一术语。此外,该解决方案将适用于EJB、Web services、异步JMS调用,甚至还有基于WLS控件的服务。由Spring实现的这种定位器模式的变体考虑了业务服务之间的一些抽象化和同质性。换句话说,Web控制器的开发人员真的可以不考虑他们所使用的服务的种类,一个类似于“WLS控件”但是更通用的概念。
IoC框架大大改进了这种模式的效用,而且实际上废除了复杂而特殊的singleton代码来实现它。通过借用上例中引入的概念,我们实际上无需额外代码便能构建一个非常强大且无处不在的Service Locator模式。为此,在一开始有一个简单的要求,即Web操作的开发人员应专门处理实现接口的那些事情。这基本上已经通过EJB编程实现,但并不是说Web操作的开发人员处理的服务必须通过EJB来实现。它们可能只是普通Java对象或Web services。要点是应当通过接口(这样实现能够换入换出)来编写服务程序,并且运行时配置能够由Spring处理。
Spring之所以非常适合于Service Locator模式,是因为它或多或少能够统一地处理不同类型的对象。通过少许的规划和大量使用IoC,我们多少都能够以一种通用方式来处理大多数对象,而不用管它们的特性(EJB、POJO等等)如何,并且不会引起Singleton工厂类的增加。这使Web层编程变得更加轻松和灵活。
我们先来看一个关于这种模式如何应用于EJB的例子。我们都知道使用EJB可能是最复杂的方法,因为要将一个活动的引用引入EJB要做很多工作。若使用Spring,建议用EJB接口扩展非特定于EJB的业务接口。这样做有两个目的:保持两个接口自动同步,以及帮助保证业务服务对非EJB实现是可交换的,以便进行测试或清除(stubbing)。我们可以利用Spring固有的实用工具来定位和创建EJB实例,同时为我们处理所有难以处理的工作。相应代码如下所示:
<bean id="myBizServiceRef"
class="org.springframework.ejb.access.
LocalStatelessSessionProxyFactoryBean">
<property name="jndiName">
<value>myBizComponent</value>
</property>
<property name="businessInterface">
<value>
yourco.project.biz.MyBizInterface
</value>
</property>
</bean>
接下来可以检索bean并开始使用它,方法如下:
MyBizInterface myService = bf.getBean("myBizServiceRef");
这将返回Spring动态创建并包装了底层目标(在本例中是一个本地EJB实例)的一个对象。这种方法非常好,因为它完全隐藏了我们在处理EJB这一事实。我们将与一个实现简单业务接口的代理对象交互。Spring已经基于“真正的”业务对象考虑周到地动态生成了该对象。所包装的对象当然就是Spring定位和检索引用所要获得的本地EJB。此外,您还会注意到,这种代码形式与前面用于检索tempSensor对象的代码完全相同。
