我酷下载
您的位置:首页-> 技术文章-> -> Java-> POJO应用架构:Spring与EJB 3.0的对比(二)

阅读排行




POJO应用架构:Spring与EJB 3.0的对比(二)

作者未知 来源未知 加入时间:2005-10-16 人气:197
宣告式服务(Declarative Services)

  Spring和EJB 3.0都把运行时服务(例如事务、安全性、日志记录、消息和定制服务)捆绑到应用程序上。由于这些服务都没有直接地与应用程序的业务逻辑相关联,因此它们不由应用程序自身来管理。作为代替,这些服务是在运行时由服务容器(例如Spring或EJB 3.0)透明地应用在程序上的。开发者(或管理员)配置容器并告诉容器如何/什么时候应用服务。

  EJB 3.0使用Java注释配置宣告式服务,而Spring使用XML配置文件。在大多数情况下,对于这类服务,EJB 3.0注释方法更加简单,更加优雅。下面是一个在EJB 3.0中给POJO方法应用事务服务的例子。


public class Foo {

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public bar () {
// 执行某些操作 ...
}
}

  你也可以在一个代码片断中定义多个属性,应用多个服务。下面是一个在EJB 3.0中同时给POJO应用了事务和安全性服务的例子:


@SecurityDomain("other")
public class Foo {

@RolesAllowed({"managers"})
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public bar () {
// 执行某些操作 ...
}
}

  使用XML指定代码属性和配置宣告式服务可能导致冗长的和不稳定的配置文件。下面是一个在Spring应用程序中利用XML元素给Foo.bar()方法应用一个非常简单的Hibernate事务服务的例子:


<!-- 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 -- omitted here -->
<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>

  如果你给同一个POJO添加多个拦截器(interceptor,例如安全性拦截器),那么XML的复杂程度会呈几何级数增长。Spring意识到了只使用XML配置文件的局限性,它现在支持在Java源代码中使用Apache通用元数据指定事务属性。在最新的Spring 1.2中,还支持JDK-1.5样式的注释。如果你要使用事务元数据,就需要把上面的transactionAttributeSource bean改变成AttributesTransactionAttributeSource示例,并增加与元数据拦截器相关的额外配置。


<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"/>

  当你拥有很多事务方法的时候,Spring元数据简化了transactionAttributeSource元素。但是它没有解决XML配置文件的基本问题--冗长和脆弱,还是需要使用事务拦截器、transactionManager和transactionAttributeSource。

  依赖注入(Dependency Injection)

  中间件容器的关键优势在于它们允许开发者建立松散耦合的应用程序。服务的客户端只需要知道服务的接口。容器用具体的实现来初始化服务对象,并使客户端能够访问它们。这就允许了容器在不同的服务实现之间进行切换,而不需要改变接口或客户端代码。

  依赖注入(DI)模式是实现松散耦合的应用程序的最好的方法之一。它比旧方法(例如通过JNDI的依赖查找或容器回调)更易于使用、更优雅。使用DI的时候,框架组件充当建立服务对象的对象工厂,并根据运行时配置,把这些服务对象注入应用程序POJO中。从应用程序开发者的角度来看,当客户端POJO需要使用某种服务对象的时候,它们会自动地获取该对象。

  Spring和EJB 3.0都给DI模式提供了广泛的支持,但是它们之间有一些深刻的差异。Spring支持普通的、但是复杂的、基于XML配置文件的DI API;EJB 3.0通过简单的注释支持大多数通用服务对象(例如EJB和上下文关系对象)和JNDI对象的注入操作。

  EJB 3.0 DI注释非常简洁,易于使用。@Resource标签注入大多数通用服务对象和JNDI对象。下面的例子演示了如何把JNDI中的服务器的默认DataSource对象注入POJO的一个字段变量中。DefaultDS是JNDI用于表示DataSource的名称。在第一次使用myDb变量之前,会把正确的值自动地赋给它。


public class FooDao {

@Resource (name="DefaultDS")
DataSource myDb;

// 使用 myDb 获取数据库的JDBC连接
}

  作为对字段变量直接注入的补充,我们还可以使用EJB 3.0中的@Resource注释,通过设置(setter)方法来注入对象。例如,下面的例子就注入了一个对话上下文关系(context)对象。应用程序一直没有显式调用设置方法--该方法在被其它的任何方法调用之前,会先被容器调用。


@Resource
public void setSessionContext (SessionContext ctx) {
sessionCtx = ctx;
}

  对于更加复杂的服务对象,已经定义了一些专用的注入注释。例如,@EJB注释用于注入EJB stub,@PersistenceContext注释用于注入EntityManager对象(它为EJB 3.0实体bean处理数据库访问)。下面的例子演示了如何向一个有状态的对话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);
}
}

  EJB 3.0规范定义了可以通过注释注入的服务器资源。但是它不支持用户自定义的应用程序POJO的彼此相互注入。

  在Spring中,你首先需要为POJO的服务对象定义一个设置方法(或者带参数的构造函数)。下面的例子显示POJO需要一个指向Hibernate对话工厂的指针。


public class FooDao {

HibernateTemplate hibernateTemplate;

public void setHibernateTemplate (HibernateTemplate ht) {
hibernateTemplate = ht;
}

// 使用 Hibernate 模板访问数据
public Foo getFoo (Integer id) {
return (Foo) hibernateTemplate.load (Foo.class, id);
}
}

  接下来,你可以指定容器如何在运行时通过XML元素链获取服务对象并把它捆绑到POJO上。下面的例子演示了把数据源捆绑到Hibernate对话工厂,把对话捆绑到Hibernate模板对象,最后把模板对象捆绑到应用程序POJO的XML元素。这段Spring代码如此复杂的部分原因在于我们必须手动地注入下层Hibernate管道对象,而EJB 3.0 EntityManager是由服务器自动地管理和配置的。但是这又让我们回到了Spring没有像EJB 3.0那样与服务紧密集成的讨论中了。


<bean id="dataSource"
class="org.springframework
.jndi.JndiObjectFactoryBean">
<property name="jndiname">
<value>java:comp/env/jdbc/MyDataSource</value>
</property>
</bean>

<bean id="sessionFactory"
class="org.springframework.orm
.hibernate.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>

<bean id="hibernateTemplate"
class="org.springframework.orm
.hibernate.HibernateTemplate">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>

<bean id="fooDao" class="FooDao">
<property name="hibernateTemplate">
<ref bean="hibernateTemplate"/>
</property>
</bean>

<!-- The hibernateTemplate can be injected
into more DAO objects -->

  尽管在Spring中基于XML的依赖注入语法是复杂的,但是它却很强大。你可以把任何POJO(包括你在应用程序中定义的)注入另一个POJO。如果你真的希望在EJB 3.0应用程序中使用Spring的依赖注入能力,你可以通过JNDI把Spring bean工厂注入EJB中。在某些EJB 3.0应用程序服务器中,厂商可能定义了额外的非标准的API,以注入任意的POJO。其中一个很好的例子是JBoss MicroContainer,它甚至比Spring更普通,因为它处理了面向方面编程(AOP)的依赖性。

  结论

  尽管Spring和EJB 3.0的目标都是为松散耦合的POJO提供企业级服务,但是它们是使用截然不同的方法来达到这个目标的。在这两个框架组件中都大量地使用了依赖注入(DI)。

  使用EJB 3.0的时候,基于标准的方法、注释的大量使用、以及与应用程序服务器的紧密集成形成了强大的厂商无关性和开发者的高效率。使用Spring的时候,一致地使用依赖注入和集中的XML配置文件,允许开发者构造更加灵活的应用程序,并在同一时刻使用多个应用服务。 


相关文章

相关软件

联系我们 广告服务 友情链接 版权说明 软件发布 下载帮助

CopyRight
2005-2016 www.5qcn.net All Rights Reserved 版权所有 【我酷】下载