服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > 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所示。
  
 如何在ejb应用程序中使用spring(图一)
  图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的时候,如何使用这种方法的。
  
 如何在ejb应用程序中使用spring(图二)

  这里,正如所期望的那样,你看到了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的组成组件共享通用的

扫描关注微信公众号