??xml version="1.0" encoding="utf-8" standalone="yes"?>
]]>
投票l果最l批准了JSR 316Q其中有12赞成,1反对,1无效,另有2弃权?
投了赞成的包括Sun、OracleQ正在试囑ƈ购Sun的过E之中)、IBM、Google和Red Hat。Apache基金会依旧对规范投了反对,原因依然是其Harmony目中长期与Sun存在的技术兼Ҏ工具包的争端,但Apache基金会称其投反对的目的q是不认可JSR 316的技术h倹{?
IBM投了赞成,q且同样也作了表态,它表C投是因ؓJSR的技术h|但对其许可条Ƒƈ不认同。IBM又一ơ表达了对^台支持注入编E的担心Qƈ承诺会l箋支持单一的综合可扩展注入~程模式的开发?#8220;我们仍然担心q_支持注入会给C带来不必要的ȝQ?#8221;IBM表示?
SAP和Intel投了弃权,而SpringSource没有投票?
SAP在声明中表示Ƣ迎JavaC的进展ƈ且将一如既往的支持Java开发,但对Sun作ؓJava EE 6规范的领头h没有能够按期带来承诺中的Java EE 6 TCK“充分许可条款”感到失望?
投了赞成的Red Hat则在电子邮g中说它的JBoss Seam Web 2.0应用框架已被列入到Java EE 6中?br />
]]>
爱因斯坦曄_“M事情都应该越单越好,而不是比较简单?#8221;实际上,U学真理的目的就是在假设的前提下ȝ化一个理论,q样Qh们可以去x真正重要的问题。在企业软g开发中Q道理是一L?br />
化企业Y件开发的一个关键是Q提供一个这L应用框架Q它可以使开发h员不用关注于很多复杂的问题,比如事务处理、安全和持久化等。一个设计良好的框架提升代码的可复用性,提高开发者的效率Qƈ得到更高质量的Y件。然而,目前J2EE 1.4下的EJB 2.1 框架被广泛认为是设计较差而且q度复杂的。不满于EJB2.1框架QJAVA开发者用了很多其他的中间g服务产品。最值得x的是Q以下两个框架吸引了大量开发者的兴趣和积极反馈。这两个框架很可能成为未来企业JAVA应用开发框架的选择?br />
Spring框架是一个广受欢q的但是非标准的开源框架。它主要由Interface21公司开发和控制。Spring框架的体pȝ构是Z注射依赖QDIQ模式。Spring框架使用了大量的XML配置文gQ它可以独立应用Q或者在现有的应用服务器上工作?br />
EJB 3.0框架是JCP定义的ƈ且被所有主J2EE提供商支持的标准框架。EJB 3.0规范的预发布版本目前已经有开源的和商业的实现Q如JBOSS和ORACLE。EJB 3.0大量使用了JAVA注解QJava annotationsQ是JDK1.5提供的新功能。译者注Q?br />
q两个框架有着一个共同的核心设计理念Q它们的目标是ؓ松耦合的POJOcL供中间g服务。框枉过在运行时截取执行环境Q或服务对象注给POJOcȝ方式Q将应用服务和POJOc?#8220;q接”h。POJOcLwƈ不关注如?#8220;q接”Q而且也很依赖于框架。这P开发者可以将注意力集中在业务逻辑上,可以对他们的POJOc进行与框架无关的单元测试。ƈ且,׃POJOcM需要承框架的cL实现框架提供的接口,开发者可以在更加灉|性的基础上构建承体p,和搭建应用?br />
管有着共同的理念,但这两个框架采取了不同的方式来提供POJO服务。由于已l出版了大量的比较Spring与EJB2.1或者EJB3.0与EJB2.1的书c和文章Q而没有关于比较Spring和EJB3.0的认真研IӞ因此Q本文将考察它们之间几个关键的不同,讨论他们优缺炏V本文谈到的主题同样适用于其他不太有名的但同h?#8220;松耦合POJO” 设计的企业中间g框架。我希望Q这文章可以帮助你选者最合适的你需求的框架?br />
提供商无x?br />
开发者选择JAVAq_的一个最重要的原因就是它的提供厂商无x。EJB 3.0是一个被设计为对提供商没有依赖性的开攄标准。EJB 3.0规范׃业JAVAC的主开源组l和厂商共同~写和支持的。EJB 3.0框架使开发者的应用E序实现可以独立于应用服务器。比如,JBoss的EJB 3.0的实现是ZHibernate的,Oracle的EJB 3.0实现是基于TopLink的,但是Q在JBoss或者Oracle上跑应用E序Q开发者既不需要去学习HibernateQ也不需要学习TopLink提供的独特API。厂商无xEJB 3.0框架区别于当前其他Q何的POJO中间件框架?br />
然而,p很多EJB 3.0的批评者很快指出的一P目前EJB 3.0规范正在~写q未完全完成最l发布版。很有可能,q需??q_EJB 3.0才会被主J2EE厂商完全接受。但是,q你的应用服务器本w不支持EJB 3.0Q你也可以通过下蝲和安装一?#8220;可嵌入的” EJB 3.0产品Q来使你的应用服务器支持EJB 3.0应用。比如,JBoss“可嵌入的” EJB 3.0产品是开源的Q它可以q行在Q何兼容J2SE-5.0环境下(如你的应用服务器Q,目前处于Beta版测试中。其他厂商同样可以快速发布他们自q可嵌入EJB 3.0产品Q特别是规范?#8220;数据持久?#8221;部分?br />
另一斚wQSpring一直是一个非标准的技术,而且在可以预计的未来仍将如此。尽你在Q何应用服务器都上可以使用Spring框架Q但ZSpring的应用仍然被限制于Spring本n和在你的应用中用到的Spring提供的各U特别服务?br />
׃Spring框架是一个开源项目,因此Q它使用的配|文件XML格式和开发接口都是私有的。当Ӟq种限制不仅体现在Spring框架中,其他M非标准品都会有q种限制。但是,你的Spring应用的长期生存能力将依赖于Spring目本nQ或者说Interface 21公司Q因为它雇䄦了大多数的Spring核心开发h员)。ƈ且,如果你用了Spring提供的特D服务,如Spring事务理器或者Spring MVCQ你同样被限制于Spring提供的API?br />
q且QSpring应用是知道后端服务提供者的Q即应用E序是知道服务提供者的Q这样应用程序将会在一定程度上依赖于服务提供方Q译者注Q。例如,对于数据持久化服务,Spring框架提供了不同的DAO和模板Helperc,用于JDBC、Hibernate,、iBatis和JDO。这P假如你需要改变一个Spring应用的持久化服务提供者(如,从JDBC换到HibernateQ,你将需要重构你的系l应用代码,来用新的HelpercR?br />
服务整合
Spring框架是徏立在应用服务器和服务库之上,它的服务整合代码Q如数据讉K模板和Helperc)是基于框架的Qƈ暴露l应用开发者。相反,EJB 3.0框架是紧密整合到应用服务器中的,它的服务整合代码是封装在一个标准的接口下的?br /> 因此QEJB 3.0厂商可以L的优化整体性能和开发者体验。如Q在JBoss的EJB 3.0实现中,当你通过实体理器持久化一个实体BEAN POJOӞHibernate session事务在JTA事务提交时自动提交。通过使用单的@PersistenceContext注解Q例子参看后面文章)Q你可以甚至可以实体管理器和其下的Hibernate事务l定C个有状态的session bean上。应用程序事务可以在一个session中跨多个线E,在事务性的WEB应用中这是非常有用的Q如多页面的购物车?br /> ZEJB 3.0 框架、Hibernate、和JBoss 内部Tomcat的紧密整合,上面提到的简单的整合的编E接口是可能的。Oracle的EJB 3.0框架和它内部的Toplink持久服务可以辑ֈ同样层次的整合?br /> EJB 3.0中整合服务的另一个好例子是集支持。假如你部v一个EJB 3.0应用C个集服务器Q所有的故障切换、负载均衡、分布式~存、和状态复制服务对于应用程序来_都是自动完成的。集服务被隐藏在EJB 3.0~程接口之下Q对于EJB 3.0开发者来_q些服务都是完全透明的?br /> 在Spring中,优化框架和服务之间交互更加困难一些。例如,惌用Spring的声明式事务服务来管理Hibernate事务Q必dXML配置文g中明的配置Spring的事务管理器QTransactionManagerQ和Hibernate SessionFactory对象。Spring应用开发者必自q理跨多个HTTPh的事务。ƈ且,没有单的Ҏ可以在Spring应用中实现集服?br /> 服务聚合的灵zL?/strong> ׃Spring中的服务整合代码是作为编E接口暴露给应用开发者的Q因此开发h员可以根据需要来聚合多个服务。这个特性你可以集成一个你自己?#8220;轻量”U应用服务器。Spring的一个通常的用法是Tomcat和Hibernateq接h来支持简单的数据库驱动的WEB应用E序。在q种情况下,Spring本n提供了事务管理服务,Hibernate提供了持久化服务Q这U设|本w就创徏了一个小型的应用服务器?br /> 通常QEJB 3.0应用服务器不提供l开发者这U按照你的需要来选择服务的灵zL。大多数情况Q你会得Cpd已经预先打包好的Ҏ,其中有些你可能是不需要的。然而,如果应用服务器提供了模块内部的独特设计,pJBOSS一P你可以不d心这些不必要的特性。在M情况下,d制一个全功能的应用服务器q不是一个琐而没有意义的工作?br /> 当然Q如果一个应用不是一个单一的结点,你将需要连接多个应用服务器提供的服务(如资源池、消息队列和集群Q。这U情况下Q从ȝ资源消耗上看,Spring框架和MEJB 3.0Ҏ一h“重量U?#8221;的?br /> Zq行容器外的单元试QSpring的灵zȝ服务聚合也可以来q接假对象,来替代真的服务对象。在EJB 3.0应用中,大多数的lg都是单POJOQ他们可以容易进行容器外的单元测试。但是,如果要测试与容器服务相关的服务对象(如持久化实体理器)Q更好的方式是进行容器内的测试,因ؓq样比用假对象来替代的方式更加ҎQ更加健壮,而且更加准确?br /> XML vs. 注解 从应用开发者的角度来看QSpring的编E接口主要基于XML配置文gQ而EJB 3.0则大量的使用了JAVA注解。XML文g可以表达复杂的关p,但是它们更加冗长而且不健壮。注解的方式很简单明了,但是很难去表辑֤杂的或者承性的l构?br /> Spring和EJB 3.0分别选择了XML和注解方式,q取决于框架的体pȝ构:׃注释只能描述相当的配置信息Q只有一个预先整合好的框Ӟ如大多数重要事情已经在框架中实现了)才能大量的用注释作为它的配|选项。象我们讨论的一PEJB 3.0满了这些要求,而Spring作ؓ一个一般的注射依赖框架Q它没有做到q一炏V?br /> 当然Q由于EJB 3.0和Spring怺学习了很多特性,所以,它们都在某种层次上支持XML和注释。例如,EJB 3.0中可以应用XML配置文g来作Z个选择性的机制Q用来改变注释的默认行ؓ。注释也可以用来配置一些Spring服务?br /> 研究XML和注释直接区别的最好的方式是通过例子。在下面的几节中Q我们将一L一下EJB 3.0和Spring是如何ؓ应用E序提供关键服务的?br /> 声明式服?/strong> EJB 3.0和Spring都将q行时服务(如事务管理、安全、日志、消息、和信息服务Q连接给应用E序。由于这些服务同应用E序的业务逻辑q不是直接相关的Q因此,它们不被应用E序本n来管理。相反,q些服务被服务容器(如EJB 3.0和SpringQ以不可见的方式在运行时提供l应用程序。开发h员(或系l管理员Q通过配置来告诉容器什么时候,以怎样的方式来应用q些服务?br /> EJB 3.0通过JAVA注解的方式来配置声明式服务,Spring则通过XML配置文g来完成。大多数情况下,EJB 3.0 的注解方式是应用q种服务的更加简单和优美的方式。下面是一个在EJB 3.0中对一个POJO的方法用事务管理服务的例子?br /> public class Foo { @TransactionAttribute(TransactionAttributeType.REQUIRED) public bar () { // do something ... } } 你可以对一D代码声明多个属性,q应用多个服务。下面是一个对EJB 3.0中POJOcd时用事务管理服务和安全服务的例子?br /> @SecurityDomain("other") public class Foo { @RolesAllowed({"managers"}) @TransactionAttribute(TransactionAttributeType.REQUIRED) public bar () { // do something ... } } 使用XML指定代码属性和配置声明服务导致冗长的和不桅顶的配|文件。下面是Spring应用中一个XML元素的例子,它用来在Foo.bar()Ҏ上应用一个非常简单的Hibernate事务?br /> <!-- Setup the transaction interceptor --> <bean id="foo" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="target"> <bean class="Foo"/> </property> <property name="transactionManager"> <ref bean="transactionManager"/> </property> <property name="transactionAttributeSource"> <ref bean="attributeSource"/> </property> </bean> <!-- Setup the transaction manager for Hibernate --> <bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager"> <property name="sessionFactory"> <!-- you need to setup the sessionFactory bean in yet another XML element --> <ref bean="sessionFactory"/> </property> </bean> <!-- Specify which methods to apply transaction --> <bean id="transactionAttributeSource" class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource"> <property name="properties"> <props> <prop key="bar"> </props> </property> </bean> XML文g的复杂程度将随着你对同一个POJOcd加的拦截器的数量E几何增ѝ意识到了仅使用XML配置文g的限制性,Spring支持在JAVA源代码中使用Apache Commons metadata来指定事物属性。在最新的Spring 1.2中,JDK-1.5风格的注释也被支持。ؓ了用事务元数据Q你需要ؓ上面例子中的AttributesTransactionAttributeSource 改变一个transactionAttributeSource beanQƈ且增加一个附加的对元数据拦截器的讄?br /> <bean id="autoproxy" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/> <bean id="transactionAttributeSource" class="org.springframework.transaction.interceptor.AttributesTransactionAttributeSource" autowire="constructor"/> <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor" autowire="byType"/> <bean id="transactionAdvisor" class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor" autowire="constructor"/> <bean id="attributes" class="org.springframework.metadata.commons.CommonsAttributes"/> 当你有许多事务方法时QSpring元数据简化了transactionAttributeSource元素。但是它没有解决XML配置文g的根本问题:仍然需要冗长的、易错的事务拦截器,事务理器,和事务属性?br /> 注射依赖 中间件容器的一个主要优Ҏ它们使得E序开发h员可以去构徏松耦合的应用程序。服务用者仅仅需要知道服务接口就可以使用服务。容器把具体的服务实现实例化Q然后将它们提供l服务用者。这P容器可以在可替换的服务实C间进行切换,而不改变服务接口和服务用者代码?br /> 注射依赖模式是实现松耦合应用E序的一个最好的方式。比起以前的方式Q如通过JNDIq行查找或回调容器,注射依赖模式更容易用,而且更加优美。用注依赖模式,框架扮演了构建服务的对象工厂角色Q然后根据运行时的配|,把这些服务对象注到应用E序的POJOcM。从E序开发h员的角度看,作ؓ客户端用者的POJO在需要用服务对象前p动的得到了它们?br /> Spring ?EJB 3.0都提供了大量的DI模式支持。但是,它们之间也有着Ҏ的不同。Spring支持了通常意义上的但是复杂的基于XML配置文g的注依赖APIQEJB 3.0支持的注大多数通用服务对象Q如QEJB和容器对象)和JNDI对象Q它通过单的JAVA注解来完成?br /> EJB 3.0的注注解相当的z易用。@Resource标签注射大多数的通过服务对象和JNDI对象。下面的例子昄了如何将JNDI提供的服务器~剩数据源对象注给一个POJO的一个字DcDefaultDS是这个数据源的JNDI名字。myDb 变量在第一ơ被使用前就自动被赋予了正确的倹{?br /> public class FooDao { @Resource (name="DefaultDS") DataSource myDb; // Use myDb to get JDBC connection to the database } 在EJB 3.0中,注释@Resource不仅可以直接注射l属性变量,它也可以通过setterҎ来完成注。下面的例子一个session上下文对象通过setterҎ注射l用者。应用程序不用显C的调用setterҎQ在M其他Ҏ被调用前容器调用setterҎ完成注射?br /> @Resource public void setSessionContext (SessionContext ctx) { sessionCtx = ctx; } 对于更复杂的服务对象Q还有一些特D的注射注解。例如,@EJB 注解被用来注EJB stubsQ@PersistenceContext注解被用来注实体管理器对象Q这些对象负责处理EJB 3.0实体Bean的数据访问操作?下面的例子给出如何将一个实体管理器注射C个有状态Session Bean中。@PersistenceContext注解的类型属性描qC被注的的实体管理器有一个扩展的事务容器Q它不会随着JTA事务理器自动提交事务,因此它可以应用在当session中有多次操作的应用事务管理时?br /> @Stateful public class FooBean implements Foo, Serializable { @PersistenceContext( type=PersistenceContextType.EXTENDED ) protected EntityManager em; public Foo getFoo (Integer id) { return (Foo) em.find(Foo.class, id); } } EJB 3.0 规范定义了可以通过注解来被注射使用的服务器资源。但是,它不支持用户自定义的POJOcM间的怺注射?br />
在Spring中,Z服务对象注到你的POJOcMQ你首先需要定义一个setterҎ(或有参数的构造函? 。下面的例子演示?POJO cM一个Hibernate session 工厂的属性?br />
public class FooDao { |