EJB3.0和Spring比较
?
public class Foo {
?
???
?
????@TransactionAttribute(TransactionAttributeType.REQUIRED)
?
??? public bar () {
?
????? // do something ...
?
??? }???
?
}
?
?
可以对同一代码段定义多个属性,从而申请多个运行时服务,例子如下:
?
@SecurityDomain("other")
?
public class Foo {
?
???
?
????@RolesAllowed({"managers"})
?
??? @TransactionAttribute(TransactionAttributeType.REQUIRED)
?
??? public bar () {
?
????? // do something ...
?
??? }??
?
}
?
?
使用XML来定义属性并配置声明式服务的结果将式一个冗长而不稳定的配置文件。以下即是一个例子,通过一个XML元素为一个Spring应用中Foo.bar()方法声明Hibernate事务支持。
?
<!-- Setup the transaction interceptor -->
?
<bean id="foo"
?
??cellpadding="0" cellspacing="0" border="1">?
<bean id="autoproxy"
?
??? cellpadding="0" cellspacing="0" border="1">?
public class FooDao {
?
?
??? @Resource (name="DefaultDS")
?
??? DataSource myDb;
?
???
?
????// Use myDb to get JDBC connection to the database
?
}
?
?
作为补充,EJB3.0中@Resource注释属性也可以通过setter方法来设置。下例注入一个会话上下文。应用程序无需显式的去调用setter方法,而只是由容器在其他方法被调用之前引入。
?
@Resource
?
public void setSessionContext (SessionContext ctx) {
?
????sessionCtx = ctx;
?
}
?
?
对于更复杂的服务对象,某些特殊的注入注释并不可用。如:@EJB用于注入EJB Stub,而@PersistenceContext用于注入EntityManager对象,以便为EJB3.0实体bean处理数据访问。下例显示如何向一个有状态的session bean注入一个EntityManager。@PersistenceContext注释的type属性定义了注入的EntityManager对象拥有一个扩展的事务上下文。这代表事务不会由JTA事务管理器自动的提交,从而可以在一个会话中跨线程的使用。
?
@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);
?
??? }
?
}
?
?
EJB3.0规范定义了可以通过注释去注入的服务资源。但不支持定义用户定义的应用POJO被注入到其他应用中。
在Spring中,你首先需要为你POJO中的服务对象定义一个setter方法,(或带参数的构造函数)。下例显示POJO需要应用Hibernate session factory的情况。
?
public class FooDao {
?
???
?
????HibernateTemplate hibernateTemplate;
?
???
?
????public void setHibernateTemplate (HibernateTemplate ht) {
?
??????? hibernateTemplate = ht;
?
??? }
?
???
?
????// Use hibernateTemplate to access data via Hibernate
?
??? public Foo getFoo (Integer id) {
?
??????? return (Foo) hibernateTemplate.load (Foo.class, id);
?
??? }
?
}
?
?
然后,你就可以定义容器如何去取得服务对象,并在运行时POJO与XML元素关联起来。下例显示通过XML元素定义将数据源与Hibernate session factory联系起来,session factory和一个Hibernate临时对象联系起来,并最终和应用POJO对象联系起来。Spring代码的复杂性有部分来自于必须人工处理这些注入的底层,这个EJB3.0的EntityManager通过服务器自动的管理配置形成对比。但Spring没有向EJB3.0那样和服务紧密集成。
?
<bean id="dataSource"
?
??class="FooDao">
?
??? <property name="hibernateTemplate">
?
??????? <ref bean="hibernateTemplate"/>
?
??? </property>
?
</bean>
?
?
<!-- The hibernateTemplate can be injected
?
??????? into more DAO objects -->
?
?
尽管Spring基于XML的依赖注入语法复杂,但非常强大。你可以在你应用中的任意POJO注入任何POJO,包括自定义的。如果你真的很希望在EJB3.0的应用中使用Spring的DI能力,你可以通过JNDI向EJB中注入Spring bean factory。在某些EJB3.0应用服务中,厂商可能会定义额外的非标准的API来注入POJO。一个很好的例子是JBoss MicroContainer,甚至比Spring更普遍的支持AOP。
7.?原文结论
?
?
尽管Spring和EJB3.0都瞄准提供低藕合POJO的企业服务,但使用了非常不同的方法来实现。DI模式在两种框架中都得到大量的使用。
EJB3.0是基于标准化的实现,大量使用注释,和应用服务紧密集成。带来的结果是厂商独立和开发者生产力的提高。Spring,使用依赖注入,并且围绕XML配置文件,给开发者带来很大的灵活性,并可以同时在不同的应用服务上运行。