[转载]IBM WebSphere 开发者技术期刊: Roland Barcia 的提示

IBM WebSphere 开发者技术期刊: Roland Barcia 的提示

EJB 规范中最困扰的五个方面


EJB™ 技术具有很高的价值,但也存在一定的缺点。本文探讨了多种 bean 类型中存在的缺点和分歧,并就在这些方面如何改进 EJB 规范,提出了建议。

Enterprise JavaBean™ (EJB) 规范已经使用很多年了,并且在此期间已经发展成为企业解决方案的创建平台。但是任何技术都不是十全十美的。EJB 规范的许多方面已经开始受到仔细审查。例如它使用实体 Bean 作为持久性的解决方案, 这种方式已经开始引起争论,因为有些人找到了可以获得持久性的解决方案,例如通过 Hibernate 或者 JDO 的方法。我将在以后的文章中对持久性问题的进行讨论。这里,我将从总体上列出 EJB 规范中几个让我困惑的方面,通过讨论不同的 bean 类型分析每个问题的原因所在,并对如何使得这些规范更好的解决这些问题给出自己的建议。我将在已经理解该规范的前提下着重介绍 EJB 3.0 规范是如何解决问题的。

我并不认为其他的框架机制能够代替 EJB 规范,指出这一点很重要。我仍然认为 EJB 组件可以在企业开发中占有一席之地。例如,无状态会话 bean 和消息驱动的 bean 是每个版本中不断发展的技术。我希望这些规范能够不断得到发展以解决开发人员、部署人员和构建人员所面临的困难,而不是陷入到编写代码的风格中。

1. 不存在 EJB JAR 级的命名空间

J2EE 1.3 规范中引入了资源引用和 EJB 引用的概念,它们作为一种机制能在调用组件和实际组件之间提供间接级联系。例如,可以在用于 JDBC 资源的部署描述符中声明一个资源引用,如 jdbc/MyDSRef。在 J2EE 组件内部,可以使用 JNDI API 查找那些使用 java:comp/env/jdbc/MyDSRef 字符串的资源。在服务器上,可以将数据源定义为其他名称,例如 jdbc/MyDS。在实施部署的时候,能够将部署描述符上的引用名称与 JNDI 中定义的资源的实际名字匹配起来。

该模型存在许多好处:

  • 能够将应用程序部署到不同的服务器中,同一资源可能有不同的名称。使应用程序通过不同的测试环境进行测试,最后形成产品时,这种情况很常见。
  • 能 够在引用中附加特定的元数据,来指示调用组建的行为。这样的线索使得应用程序服务器能够优化行为。例如对表格来说,能够使用特定的分离级别在数据源中定义 一个资源应用,同时使用不同的分离级别在相同数据库中定义另一个引用。正是依赖于这种所期望的分离,能够通过相关的引用查看这些资源。这样可以使得开发人 员不必与底层的数据库 API 交互。同时还可以连接到策略和安全性证书等。

Web 应用程序中定义资源引用的方式与 EJB 容器中的定义方式有根本区别:

  • WAR 文件中存在一个用于所有 Web 组件的命名空间,可以使用它来定义资源引用。这就意味着可以将 EJB 资源引用和数据资源引用定义在同一个地方,并且每个 servlet 或者 JSP 都可以访问它们。
  • EJB 容器中的每个单独的 bean 上都定义了资源引用。这意味着如果有十个需要访问相同 JNDI 数据源的会话 bean,就必须在部署描述符的每个 bean 上定义相同的资源引用。

很 多时候,可能需要将资源引用扩大至 bean 级,例如想改变独立级别时。但是,很多时候存在一组采用相同方式访问数据源的 EJB 组件,反复地定义相同的资源引用就成了一件非常费力的工作。这种情况下也难以定义由多个 bean 访问的多种资源。例如,许多 EJB 组件访问相同 JMS Connection Factory 的情况并不常见,如果有 25 个会话 bean,每个 bean 访问 3 个 JMS Connection Factory,就必须在部署描述符上定义 75 资源引用,这是件可怕的事情。

在分层 的应用程序中,情况甚至更为糟糕,因为在使用 EJB 组件的 Java 类中都可能出现访问这些资源的现象。如果同一个目标在多个 bean 中复用,就必须在每个部署描述符的条目中用相同的方式定义这些引用。而且,如果等到部署的时候才将这些引用绑定到实际的 JNDI 名称,那么管理员就必须在安装应用程序的时候绑定所有的引用。

Web 容器不会出现这个问题。如果想使用 servlet 和资源来获得某种显示,可以定义多个条目,并且使得 servlet 足够智能化,这样可以基于 JNDI 名称选出合适的条目,但是没法在 EJB JAR 级上定义资源引用。因此必须修改 EJB 规范从而能在 EJB JAR 级上定义资源和 EJB 引用。虽然没有必要在 bean 级上减少资源引用,但是必须存在一种更简单的机制用于定义资源,让这些资源供多个 EJB 组件共享。

EJB 3.0 规范的早期版本并没有明确解决如何定义全局资源的问题。随着资源中注释性移植方式的使用,在多个 bean 中定义全局属性可能将变得更加困难。EJB 规范中应该有用于用户定义全局属性的小型部署描述符。


blue_rule.gif
c.gif
c.gif
u_bold.gif回页首


2. 没有单独的无状态会话 bean

6 年前我开始编写 servlet 程序时,就学着尽量不使用实现单线程模型的 servlet,原因正是与单线程请求相关的可扩展性和性能问题。我开始学习 EJB 规范时,对无状态会话 bean 都有相似地行为这个问题感到很困惑,但是却被告诉这些问题是高度可扩展的。这是因为 EJB 容器是可扩展的,就像 WebSphere® Application Server 所提供的那样,能花费时间在周围实现一个有效的共享系统。

然而,我经常 在想为什么在单线程模型 Servlet 的周围不放置一个类似的共享系统呢?使我感到更为疑惑的是为什么这里不存在无状态会话 bean 的单独版本。尽管能够保证在运行方法期间没有其他的请求可以接触到 bean 的类变量,但是 EJB 开发人员没有在 bean 类本身上使用类级别的变量,他们编写的无状态会话 bean 类似无状态组件。如果用户采用瘦虚包模式,那么用户的无状态会话可能会代表其他的类。

如果因为 servlet 是共享的而可以升级并具有高性能,那么拥有具有相同性能的无状态会话就没有意义吗?我真正想要共享的是那些线程和无状态会话 bean 所使用的资源。但是为什么就不能拥有向描述符的 Bean 片断中添加某种类型例如 或者 的 XML 标签呢?这样会给容器一个标记,表明需绕过对这些方法的共享和同步访问,将 EJB 组件作为一个单独系统。在许多情况下这样可以帮助提高性能。这种优化同样也可以应用到消息驱动的 bean。

目前我还没有看到 EJB 3.0 规范中增添这种行为。POJO 中可以注入 @Session 注释,但是我没有见到过用于无状态会话单独版本的任何注释。


blue_rule.gif
c.gif
c.gif
u_bold.gif回页首


3. EJB 组件中没有过滤性能

Servlet 2.3 规范中我最喜欢的一点就是加入了 servlet 过滤器。在多个 servlet 中加入预处理和后期处理技术会使得在应用程序组件中能够加入强大的功能。因此,EJB 组件缺少这种功能使我烦恼不已。我可以向 bean 级的一些回叫信息中添加办法,但是没有过滤技术。我认为具有事务逻辑的编码层能从这种功能中获得很大益处。EJB 的过滤功能可以在很多情况下起到作用,例如日志记录或者额外的安全性检查。

规范中没有该特性的部分原因是缺少用于引用 EJB 组件群的机制,例如,使用通配符的语言表达方式。

EJB 3.0 的规范草本中重点是简化编程模型,似乎不包括过滤性能。这将是一个很好的提高。


blue_rule.gif
c.gif
c.gif
u_bold.gif回页首


4. 无法在多个 EJB 组件中应用容器服务

Web 应用程序中可以使用通配符将 J2EE 安全角色联系到 URL 映射,这就意味着可以定义能将一个角色匹配给多个 servlet 的安全性约束。对于 EJB 组件,需要在 bean-per-bean 的基础上定义方法许可,安全性验证和事务区分同样需要这样的办法。在很多情况下需要使用相同的角色或者具有相同事务属性的角色来保护 EJB 组件群。我应该能跨多个 bean 定义这些属性。如果一次能在许多 EJB 的定义中应用容器服务,这样情况会好些。

EJB 3.0 规范并没有明确地解决这个问题,但是也间接地减少了其中的一些困难。通常,应用程序所关注的都是像事务处理这样的事情,并且这些事情可能在部署描述符中却 根本不存在。使用像 @Required 一样的注释移入所需要的事务处理行为看上去是一个很好的解决方法。其他的问题,例如安全性问题等仍然使我担心。使用 EJB 方法许可作为注释是一种好的方法,但是部署应用程序时,该规范就需要考虑如何将这些角色映射到实际的组群或者用户中去,例如,尽管已经定义了一个角色作为 注释,可能仍然需要一个包含了角色名称和到实际组群以及用户的映射的描述符。WebSphere Application Server 使用 Binding 文件完成该项任务,该规范没有详细说明已经注释了的定义角色如何映射到用户以及组。

我并没有经常地看到在许多 bean 中应用涉及全局属性的 EJB 3.0 规范。这看起来像是一个可以向规范中添加面向方面功能的合适地方。


blue_rule.gif
c.gif
c.gif
u_bold.gif回页首


5. 客户端 API

编写 EJB 客户端时,我就必须通过编程来确定该组件是 Web 服务、远程 IIOP EJB 组件还是本地 EJB 组件。这给我留下了令人畏惧的任务,需要花费时间去实现精明的业务代表,该业务代表隐藏了所使用的接口的详细信息,掩盖远程异常,或使用 PortableRemoteObject.narrow()。 为什么应用服务器不能这样做呢?请给我一个单一接口。我确实只需要一个指示器,可以是 JNDI 名称或者注释,就可以知道该接口是本地接口还是远程接口。

EJB 3.0 规范草本中通过引入 Single Business 接口,而非本地或远程接口直接解决了多个接口的问题。除此之外,规范中还去掉了用于无状态会话 bean 的 Home 接口。


blue_rule.gif
c.gif
c.gif
u_bold.gif回页首


结束语

EJB 规范中或许还有其他问题,但是这五个问题已经困扰我很长时间了。我非常希望 EJB 3.0 规范小组能够关注这些问题。但是,新的规范付诸实施还有很长的一段时间,因此现在就要将这些问题提出来。勿庸置疑,EJB 技术是成熟和稳定的,在许多情况下,与取得的成效相比,这些问题所带来的影响是相当微小的。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/374079/viewspace-130631/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/374079/viewspace-130631/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值