当前位置导航:炫浪网>>网络学院>>编程开发>>JAVA教程>>Java进阶

如何在EJB应用程序中使用Spring


  摘要
  
  在传统J2EE应用程序中,企业JavaBeans(EJB)构成了应用程序架构的基础。尽管Spring提供了EJB所提供的许多服务的简化版本,例如可申明的事务管理和对象持久性,但是,在一段时间内,许多应用程序将会继续使用EJB来构建。幸运的是,你能够在基于EJB的解决方案中使用Spring,本文是从Pro Spring中摘录,Pro Spring的作者Rob Harrop和Jan Machacek主要研究在Spring中,如何简化EJB的创建,以及Spring如何提供一个简单,友好的方法来访问EJB资源。(4600字,2005/2/14)
  
  随着Spring的发展,现在开发者第一次真正有了一个EJB的轻量级代替者。使用Spring,你能够利用许多EJB所提供的特性,例如可申明的事务管理,对象池和简单的ORM(对象角色建模)等功能。这就是说,在可预见的未来,我们期望EJB继续能够用于应用程序的开发中。尽管在本书中,我们并没有考虑使用或者不使用EJB的原因,但是,从我们在Spring方面出色的经验来看,我们推荐你尽可能的使用Spring来代替EJB。有关Spring和EJB优点和缺点更加详细的讨论,可以从Rod Johnson和Juergen Hoeller所写的书《Expert One-on-One J2EE without EJB》(Wrox, 2004)中得到。在本文中,我们将要重点讨论的是如何将Spring技术应用在使用EJB构建的系统中。
  
  Spring中对EJB的支持
  
  Spring对EJB支持能够粗略的分成两类:访问和实现。Spring中的访问支持类使你能够容易的访问EJB资源。在这一节里,我们研究Spring如何扩展基本的JNDI(Java名字目录接口)支持框架对EJB的访问,并且利用AOP(面向切面的编程)支持来提供对EJB资源的基于代理访问。
  
  Spring提供了抽象基类来支持EJB的实现,这使得创建无状态EJB,有状态EJB,消息驱动EJB,这三种类型的EJB更加简单。这三种类的使用前提并不是减轻创建EJB的负担,而是让你能够从bean内部比较容易的访问Spring管理的资源,更重要的是,这有助于将业务逻辑从EJB实现中分离,写到EJB的POJO(plain old Java object)对象中。在这里,不用担心这些模糊说法,我们将会在下一章中,使用两个例子来详细地讨论他们。
  
  我们将要构建一个使用了两个EJB服务的简单的Web应用程序。第一个无状态会话bean实现了EchoService业务逻辑接口,并且提供了简单的响应能力。第二个是有状态会话bean,它实现了CounterService业务逻辑接口,并且提供了有状态计数服务。
  
  这些是简单的例子,但是它们有助于演示所推荐的Spring中编译EJB组件的解决办法,和Spring中支持EJB的各种不同组件之间的区别。除了讨论例子中的多种部署描述符外,我们并不对EJB作更详细的研究。然而,我们将对Spring在多种组件中对EJB支持的实现,以及这种实现如何影响应用程序作深入的研究。特别地,我们研究Spring如何在ApplicationContext中定位EJB,以及如何使用JNDI基础框架来定位JNDI资源。
  
  你可能注意到,我们提到的Spring支持三种EJB,但是我们仅仅实现两种类型的EJB,无状态和有状态。消息驱动bean的支持类使用了类似于无状态和有状态会话bean所使用的模式。
  
  在Spring中构建EJB组件
  
  Spring提供了三种抽象类作为EJB bean类的基类,他们是:AbstractStatelessSessionBean,AbstractStatefulSessionBean和AbstractMessageDrivenBean。当使用Spring来构建EJB的时候,必须提供所有不同的接口和home类,但是,当实现bean类的时候,就需要从合适的Spring基类继承。Spring提供的基类允许EJB组件访问Spring的ApplicationContext,并且,这样允许这些组件访问Spring所管理的资源。
  
  在继续使用Spring来构建EchoService和CounterService bean的详细讨论之前,我们将要看看,Spring如何在ApplicationContext中定位EJB组件,以及在使用Spring时,所推荐编译EJB解决办法。
  
  Spring中EJB类层次
  
  Spring提供了定义良好的EJB支持类的类层次,如图1所示。
  
 
  图1.Spring中的EJB支持类

  
  正如你看到的那样,中心的基类AbstractEnterpriseBean暴露了beanFactoryLocator属性来允许子类访问正在使用的实例BeanFactoryLocator。在下一节中,将通过loadBeanFactory()和unloadBeanFactory()这两个方法的使用来更加详细的讨论BeanFactoryLocator接口。注意到AbstractStatelessSessionBean类已经实现了ejbCreate(),ejbActivate()和ejbPassivate()方法,而类AbstractStatefulSessionBean并没有实现这些方法。Spring对钝化bean有特别的要求,我们将在后面章节“编译有状态会话bean”中更加详细的讨论这种bean。
  
  接口BeanFactoryLocator
  
  Spring能够从ApplicationContext中装载所管理的资源,Spring中的EJB基类的主要特征就是能够访问ApplicationContext来装载资源。这种功能不是基类本身提供的,而是被委托给BeanFactoryLocator接口的实现,像显示在列表1中的情形一样。
  
  列表1. BeanFactoryLocator接口
  
  public interface BeanFactoryLocator {
  BeanFactoryReference useBeanFactory(String factoryKey)
  throws BeansException;}
  
  当Spring不能控制资源的创建,也不能自动配置资源的情况下,就需要使用BeanFactoryLocator接口。在这些情况下,BeanFactoryLocator接口允许用一种外部可配置的方式在BeanFactory中配置资源。当然,在这样的情况下,BeanFactory配置能够简单地托管资源,但是,那意味着,作为应用程序开发员的你,不能控制应用程序。使用BeanFactoryLocator,你就能够完全控制用于配置的BeanFactory或者ApplicationContext如何定位EJB组件。
  
  注意到,BeanFactoryLocator并不直接返回BeanFactory实例;而是返回一个BeanFactoryReference。BeanFactoryReference是一个轻量级BeanFactory或ApplicationContext的包装器,这个包装器允许使用BeanFactory的资源平滑地释放对BeanFactory的引用。对于BeanFactoryLocator的实现和BeanFactory或者ApplicationContext接口来说,这个接口BeanFactoryReference的实际的实现是特别的。当我们在列表13中研究状态会话bean如何释放对BeanFactoryReference的引用挂起bean时,我们将再对这个引用功能进行研究。
  
  缺省情况下,所有EJB基类使用了BeanFactoryLocator的ContextJndiBeanFactoryLocator实现。本质上来说,这个类在一个给定JNDI地点上查找一个逗号分隔的配置文件列表,并且使用这些配置文件来创建ClassPathXmlApplicationContext的实例。三个基本EJB类都通过AbstractEnterpriseBean类表现出属性beanFactoryLocator,通过设置这个属性,就能够提供你自己对于BeanFactoryLocator的不同实现。然而,如果你这样做了,那么,请注意,你的bean的每一个实例都有它自己的ContextJndiBeanFactoryLocator实例,同样,每个ContextJndiBeanFactoryLocator的实例都有它自己的ClassPathXmlApplicationContext实例。
  
  虽然为你的EJB实例创建的所有ApplicationContext实例都用同样的方式配置的,但是,所配置的bean是不一样的。考虑一下定义了echoService bean的Spring配置,其中,EchoServiceEJB将使用echoService。如果你的应用程序服务器创建100EJB个实例,那么,也创建了100个ContextJndiBeanFactoryLocator的实例,以及100个ClassPathXmlApplicationContext和echoService bean的实例
  
  如果应用程序不希望发生这种情况,那么Spring提供SingletonBeanFactoryLocator和ContextSingletonBeanFactoryLocator类来分别装载BeanFactory和ApplicationContext的单件实例。有关他们更多信息,参见这些类的Javadoc。
  
  Spring对于EJB的解决方案
  
  EJB一个最大的缺点就是要想脱离EJB容器而单独测试EJB组件非常困难,这使得EJB实现的业务逻辑的单元测试成为只有那些受虐狂者才愿意做的事。然而,这个问题的解决方法已经出现了一段时间了,它包括在POJO中实现与EJB bean类同样的业务逻辑,然后,就能将bean类委托给POJO。在Spring中,由于不必将如何定位和创建POJO的实现的任何逻辑嵌入到EJB中,这种实现就是非常简单,和灵活的。图2显示了在构建EchoService EJB的时候,如何使用这种方法的。
  
 

  这里,正如所期望的那样,你看到了bean类EchoServiceEJB实现了接口EchoService,并且注意到EchoServiceEJB依赖于接口EchoService,有一个EchoService类型的私有成员。
  
  构建一个无状态会话bean
  
  无状态会话bean是用Spring最容易构建的EJB;这是因为无论在何种情况下,它都不需要特殊的处理,并且类AbstractStatelessSessionBean实现了所有ejbXXX()方法。
  
  正如列表2所示,我们创建了服务接口。
  
  列表2. EchoService接口
  
  package com.apress.prospring.ch13.ejb;public interface EchoService {
  public String echo(String message);}
  
  注意到,服务接口不是与EJB相关的,甚至,在实现EJB的时候并不要求这个服务接口。EJB开发中传统办法是在EJB相关的本地和远程接口中定义业务逻辑方法。在这种办法中,在标准Java接口中定义业务方法,然后本地和远程bean接口扩展这个标准接口。这种服务接口不仅给本地和远程接口提供了扩展的标准接口,而且也提供了EJB bean类和POJO实现类能够实现的通用的接口。虽然我们并不推荐EJB bean类不要实现本地或者远程接口,但是实现了这个服务接口的EJB bean也不会有什么问题。通过使所有EJB的组成组件共享通用的
相关内容
赞助商链接