实现EJB
如果你选择使用EJB,Spring能在EJB实现和客户端访问EJB两方面都提供很大的好处。
对业务逻辑进行重构,把它从EJB facades中取出到POJO已经得到了广泛的认同。(不讲别的,这使得业务逻辑更容易单元测试,因为EJB严重依赖于容器而难于分离测试。)Spring为session bean和message driver bean提供了方便的超类,使得通过自动载入基于包含在EJB Jar文件中的XML文档BeanFactory让这变得很容易。
这意味着stateless session EJB可以这么获得和使用所需对象:
代码: |
import org.springframework.ejb.support.AbstractStatelessSessionBean;
public class MyEJB extends AbstractStatelessSessionBean implements MyBusinessInterface { private MyPOJO myPOJO;
protected void onEjbCreate() { this.myPOJO = getBeanFactory().getBean("myPOJO"); }
public void myBusinessMethod() { this.myPOJO.invokeMethod(); } }
|
假定MyPOJO是一个接口,它的实现类——以及任何它需要的配置,注入基本的属性和更多的合作者——在XML bean factory 定义中隐藏。
我们通过在ejb-jar.xmldeployment descriptor中名为ejb/BeanFactoryPath的环境变量定义告诉Spring去哪儿装载XML文档。如下:
代码: |
<session> <ejb-name>myComponent</ejb-name> <local-home>com.test.ejb.myEjbBeanLocalHome</local-home> <local>com.mycom.MyComponentLocal</local> <ejb-class>com.mycom.MyComponentEJB</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type>
<env-entry> <env-entry-name>ejb/BeanFactoryPath</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>/myComponent-ejb-beans.xml</env-entry-value></env-entry> </env-entry> </session>
|
myComponent-ejb-beans.xml 文件将会从classpath装载:在本例中,是EJB Jar文件的根目录。每个EJB都能指定自己的XML文档,因而这个机制能在每个EJB Jar文件中使用多次。
Spring 的超类实现了EJB中诸如setSessionContext()和ejbCreate()的生命周期管理的方法,让应用程序开发者只需选择是否实现Spring的onEjbCreate()方法。
使用EJB
Spring还让实现EJB变得更加容易。许多EJB程序使用Service Locator和Business Delegate模式。这些比在客户代码中遍布JNDI查找强多了,但是它们常见的实现方式有显著的缺点,例如:
使用EJB的典型代码依赖Service Locator或者Business Delegate singletons,使得测试难于进行。
在Service Locator模式没有使用Business Delegate的情况下,程序代码还要在EJB home中调用create()方法,并且处理可能导致的异常。因而仍然绑定在EJB API身上,忍受着EJB 编程模型的复杂度。
实现Business Delegate模式通常导致显著的代码重复,其中我们必须编写大量仅仅是调用EJB同等方法的方法。
基于这些和其他原因,传统的EJB访问,如在Sun Adventure Builder和OTN J2EE Virtual Shopping Mall中展示的那样,会降低生产率并且带来显著的复杂度。
Spring通过引入codeless business delegate前进了一步。有了Spring,你不再需要再编写另一个Service Locator,另一个JNDI查找,或者在硬编码的Business Delegate中重复代码,除非你肯定这增加了价值。
例如,假定我们有使用local EJB的web controller。我们将遵循最佳实践,使用EJB Business Methods Interface模式,EJB的local interface extend非EJB专有的业务方法接口。(这么做的主要的一个原因是确保在本地接口和bean实现类中方法签名的自动同步。)让我们调用这个业务方法接口MyComponent。当然我们还需要实现local home接口并且提供实现SessionBean和MyComponent业务方法的bean的实现类。
用了Spring EJB 访问,我们把我们的web层controller和EJB实现挂接上所需要进行的Java编码仅仅是在我们的controller中暴露一个类型MyComponent的setter方法。这将如下保存作为实例变量的引用:
代码: |
private MyComponent myComponent;
public void setMyComponent(MyComponent myComponent) { this.myComponent = myComponent; }
|
我们随后在任何业务方法中使用这个实例变量。
Spring自动完称剩下的工作,通过像这样的XML bean定义。LocalStatelessSessionProxyFactoryBean是一个可以用于任何EJB的通用factory bean。它创建的对象能够自动被Spring转型为MyComponent类型。
代码: |
<bean id="myComponent" class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
<property name="jndiName"><value>myComponent</value></property> <property name="businessInterface"><value>com.mycom.MyComponent</value></property> </bean>
<bean id="myController" class = "com.mycom.myController" > <property name="myComponent"><ref bean="myComponent"/></property> </bean>
|
在幕后有许多魔法般的事情发生,Spring AOP framework的殷勤,虽然不强迫你使用AOP的概念享受这些结果。“myComponent”bean定义为EJB创建一个代理,它实现了业务方法的接口。EJB local home在启动的时候被缓存,因而只需要一次JNDI查找。每次EJB被调用的时候,代理调用local EJB中的create()方法并且调用EJB中对应的业务方法。
myController bean定义为这个代理设置controller类的myController属性。
这个EJB访问机制极大简化了应用程序的代码:
Web层的代码不依赖于EJB的使用。如果你想要使用POJO,mock object或者其他test stub替代EJB引用,我们可以简单地改动一下myComponent bean定义而不影响一行Java代码
我们还不需要写一行JNDI查找或者其他EJB plumbing code。
在实际程序中的性能测试和经验标明这种方法(包括对目标EJB的反射调用)的性能影响是很小的,在典型的应用中检测不出。记住无论如何我们都不希望使用fine-grained的EJB调用,因为会有有关应用服务器上的EJB的底层架构方面的代价。
我们可以把相同方法应用于远程EJB,通过类似org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean factory bean的方法。然而我们无法隐藏远程EJB的业务方法接口中的RemoteException。
posted on 2005-10-26 16:08
Sung 阅读(256)
评论(0) 编辑 收藏 所属分类:
Java