方兴未艾的新范式:AOP
最后不得不提的是,一种新的编程模型正在浮出水面。那是一种更为通用的解决方案,仅仅其中的一部分就能够提供EJB大多数有价值的能力,那就是面向方面的编程(Aspect Oriented Programming,AOP)。在J2EE应用开发中,我们主要用到AOP的拦截(interception)能力,它为我们提供了“在任何对象的方法调用前/后加入自定义行为”的能力,这使得我们可以处理企业应用中的横切(crosscutting)关注点(即:同时作用于多个对象的关注点),并且仍然保持强类型(不需要改变方法签名)。例如,我们可以在一个应该具有事务的方法调用前开始一个事务,在方法返回时提交或者回滚。使用AOP让我们可以把 “与事务管理相关的重复劳动”放进一个框架内。另外一个很适合使用AOP的场合则是自定义安全检查。
我把AOP看作是OOP的补充,而不是竞争对手。OOP在通常的场合下工作得很好,但在特定的领域里却有所欠缺:举例来说,如果我们必须为多个对象和方法应用相同的事务行为,我们需要将同样的代码剪切/粘贴到每一个方法里。AOP让我们可以把这类问题封装到方面(aspect)中,从而更好地实现模块化。AOP定义了“切入点”(pointcut)的概念,让开发者可以从另一个角度来思考程序的结构,从而弥补了OOP的某些缺陷:如果需要对一组方法施加横切的行为,就应该拦截这些方法。
在这里,你可以看到与EJB的相似之处:EJB服务说到底就是拦截。客户端执行EJB上的一个方法,EJB容器则使用拦截来提供安全检查、线程管理、声明性事务管理等服务,这与AOP拦截是相同的概念。这是一个强大的概念, EJB最重要的价值都是由它提供的。
为了获得这些服务,AOP比EJB更有吸引力,因为它对业务对象的要求更少。例如,它们通常不需要依赖一个特定的API(譬如EJB API);它们可以是POJO,从而使得开发更加容易,并且可以获得对象模型的所有利益。AOP的另一个优点是:它比EJB允许更大的开放性。譬如说,只要愿意,我们就可以自定义应用方面;而使用 EJB,我们就只能使用那些系统级的方面——这些方面是EJB规范规定、由EJB容器实现的。
EJB为我们提供了什么?
有经验的系统架构师倾向于只使用EJB的一小部分。毫无争议,无状态session bean(Stateless Session Bean,SLSB)是EJB中最有用的,然后是message-driven bean(用于异步操作)。几乎同样毫无争议的,有状态session bean的价值是可疑的。EJB规范使得容器很难让有状态session bean具有与HTTP session对象同样的稳定性,这意味着在大多数场合HTTP session对象是更好的选择。entity bean则可能是EJB规范中最虚弱的部分,它的性能相当差,并且没能解决好O/R映射中最重要的问题,而这恰好是人们希望它完成的工作。
为什么SLSB如此流行?因为它们是简单的组件(至少按照EJB标准是这样),并且对一些企业系统常见的问题提供了一个相当好的解决方案。下面,让我们逐一审视SLSB提供的主要服务:
声明性事务管理
SLSB最有价值的服务可能就是容器管理的事务(Container-Managed Transaction,CMT)了。尽管最终通过JTS/JTA协调事务的是J2EE服务器而不是EJB容器,但SLSB让我们可以使用声明性、而非编程性的事务管理。我们可以在Java代码之外告诉EJB容器如何划定事务边界。当然,如果想要回滚事务,我们需要使用EJB API,但是在理想的状态下中,我们不必为事务管理写哪怕一行代码,也不需要使用复杂的JTA API。
尽管EJB CMT对于大多数应用来说很有价值,但要处理一些复杂的事务管理问题就显得力不从心了。譬如说,有时一个业务操作需要多个事务,如果每次事务都通过一个 EJB入口点调用一个EJB方法,这就比通过编程方式界定事务更复杂了。乐观的锁定策略也会成为一个问题。如果我们使用声明性事务来驱动一种持久技术(例如TopLink)执行乐观事务,乐观并发异常将在容器提交事务之后才出现,而此时时应用代码已经将控制权交给了EJB容器,很难重新控制程序的运转。 EJB没有为这类更复杂的场景提供良好的支持。如果使用Bean管理事务(Bean-Managed Transaction,BMT)的EJB,则需要从JNDI得到JTA UserTranscation对象,然后就像在应用服务器中运行的其他对象一样直接使用JTA API。在同一个EJB中混合BMT和CMT也是不可能的,所以如果只有一个方法需要复杂的事务行为,所有的其它方法都必须承担BMT和JTA的复杂性。
然而,尽管CMT不能解决所有的问题,对于大多数应用场景,它仍然不失为一种出色的技术,理应成为人们使用session bean的一个重要理由。
