Spring Framework 中文文档

4.3.21.RELEASE

39. Classic Spring 用法

本附录讨论了一些经典的 Spring 使用模式,作为开发人员维护 legacy Spring applications 的 reference。这些使用模式不再反映使用这些 features 的推荐方式,并且 reference 手册的相应部分介绍了当前推荐的用法。

39.1 经典 ORM 用法

本节介绍了 legacy Spring application 中可能遇到的经典使用模式。有关当前推荐的使用模式,请参阅ORM章节。

39.1.1 Hibernate

对于 Hibernate 目前推荐的使用模式,请参阅第 20.3 节,“ Hibernate”

HibernateTemplate

对于可以作为任何自定义数据访问 object 或业务服务的一部分的方法,模板的基本编程 model 如下所示。对周围的 object 的 implementation 没有任何限制,它只需要提供一个 Hibernate SessionFactory。它可以从任何地方获得后者,但最好是从 Spring IoC 容器中获取 bean reference - 通过一个简单的setSessionFactory(..) bean property setter。以下代码段在 Spring 容器中显示 DAO 定义,引用上面定义的SessionFactory,以及 DAO 方法 implementation 的 example。

<beans>

    <bean id="myProductDao" class="product.ProductDaoImpl">
        <property name="sessionFactory" ref="mySessionFactory"/>
    </bean>

</beans>
public class ProductDaoImpl implements ProductDao {

    private HibernateTemplate hibernateTemplate;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.hibernateTemplate = new HibernateTemplate(sessionFactory);
    }

    public Collection loadProductsByCategory(String category) throws DataAccessException {
        return this.hibernateTemplate.find("from test.Product product where product.category=?", category);
    }
}

HibernateTemplate class 提供了许多方法来镜像 Hibernate Session接口上公开的方法,此外还有许多方便的方法,例如上面显示的方法。如果您需要访问Session以调用HibernateTemplate上未公开的方法,您可以始终下拉到 callback-based 方法。

public class ProductDaoImpl implements ProductDao {

    private HibernateTemplate hibernateTemplate;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.hibernateTemplate = new HibernateTemplate(sessionFactory);
    }

    public Collection loadProductsByCategory(final String category) throws DataAccessException {
        return this.hibernateTemplate.execute(new HibernateCallback() {
            public Object doInHibernate(Session session) {
                Criteria criteria = session.createCriteria(Product.class);
                criteria.add(Expression.eq("category", category));
                criteria.setMaxResults(6);
                return criteria.list();
            }
        };
    }

}

回调 implementation 可以有效地用于任何 Hibernate 数据访问。 HibernateTemplate将确保Session实例正确打开和关闭,并自动参与 transactions。模板实例是 thread-safe 并且可重用,因此可以将它们保存为周围 class 的实例变量。对于简单的单个 step 操作(如单个 find,load,saveOrUpdate 或 delete 调用),HibernateTemplate提供了可替代此类 line 回调 implementations 的替代便捷方法。此外,Spring 提供了一个方便的HibernateDaoSupport base class,它提供了setSessionFactory(..)方法来接收SessionFactorygetSessionFactory()getHibernateTemplate()供子类使用。结合使用,这可以实现非常简单的 DAO implementation,以满足典型要求:

public class ProductDaoImpl extends HibernateDaoSupport implements ProductDao {

    public Collection loadProductsByCategory(String category) throws DataAccessException {
        return this.getHibernateTemplate().find(
            "from test.Product product where product.category=?", category);
    }

}

在没有回调的情况下实现 Spring-based DAO

作为使用 Spring 的HibernateTemplate来实现 DAO 的替代方法,数据访问 code 也可以用更传统的方式编写,而不需要在回调中包装 Hibernate 访问 code,同时仍然尊重和参与 Spring 的通用DataAccessException层次结构。 HibernateDaoSupport base class 提供了访问当前 transactional Session并在这种情况下转换 exceptions 的方法;类似的方法也可用作SessionFactoryUtils class 上的静态助手。请注意,此类 code 通常会将false作为getSession(..)方法allowCreate参数的 value 传递,以在 transaction 中强制 running(这样可以避免关闭返回的Session,因为其生命周期由 transaction 管理)。

public class HibernateProductDao extends HibernateDaoSupport implements ProductDao {

    public Collection loadProductsByCategory(String category) throws DataAccessException, MyException {
        Session session = getSession(false);
        try {
            Query query = session.createQuery("from test.Product product where product.category=?");
            query.setString(0, category);
            List result = query.list();
            if (result == null) {
                throw new MyException("No search results.");
            }
            return result;
        }
        catch (HibernateException ex) {
            throw convertHibernateAccessException(ex);
        }
    }
}

这种直接 Hibernate 访问 code 的优点是它允许在数据访问 code 中抛出任何已检查的 application exception;将此与HibernateTemplate class 进行对比,后者仅限于在回调中仅抛出未经检查的 exceptions。请注意,您通常可以在回调之后推迟相应的检查并抛出 application exceptions,这仍然允许使用HibernateTemplate。通常,HibernateTemplate class'便捷方法对于许多场景来说更简单,更方便。

39.2 JMS 用法

Spring 的 JMS 支持的一个好处是保护用户免受 JMS 1.0.2 和 1.1 API 之间的差异。 (有关两个 API 之间差异的说明,请参阅域统一的侧栏)。由于现在只需遇到 JMS 1.1 API,因此在 Spring 3.0 中不推荐使用基于 JMS 1.0.2 API 的 classes。本节介绍 Spring JMS 对 JMS 1.0.2 已弃用的 classes 的支持。


域名统一

JMS 规范有两个主要版本,1.0.2 和 1.1.

JMS 1.0.2 定义了两种类型的消息传递域,point-to-point(队列)和 publish/subscribe(主题)。 1.0.2 API 通过为每个域提供 parallel class 层次结构来反映这两个消息传递域。因此,client application 在使用 JMS API 时变为特定于域的。 JMS 1.1 引入了域统一的概念,最大限度地减少了两个域之间的功能差异和 client API 差异。作为已删除的功能差异的示例,如果使用 JMS 1.1 提供程序,则可以在事务上使用来自一个域的消息,并使用相同的Session在另一个域上生成消息。

JMS 1.1 规范于 2002 年 4 月发布,并于 2003 年 11 月作为 J2EE 1.4 的一部分合并。因此,仍然广泛使用的 common J2EE 1.3 application 服务器(例如 BEA WebLogic 8.1 和 IBM WebSphere 5.1)基于 JMS 1.0.2.


39.2.1 JmsTemplate

位于包org.springframework.jms.core中 class JmsTemplate102提供了JmsTemplate描述 JMS 章节的所有 features,但它基于 JMS 1.0.2 API 而不是 JMS 1.1 API。因此,如果您使用的是 JmsTemplate102,则需要设置 boolean property pubSubDomain以配置JmsTemplate,并了解正在使用的 JMS 域。默认情况下,此 property 的 value 为 false,表示将使用 point-to-point 域 Queues。

39.2.2 异步消息接收

MessageListenerAdapter与 Spring 的message listener 容器一起使用,通过将几乎任何 class 暴露为 Message-driven POJO 来支持异步消息接收。如果您使用的是 JMS 1.0.2 API,则需要使用 1.0.2 特定的 classes,例如MessageListenerAdapter102SimpleMessageListenerContainer102DefaultMessageListenerContainer102。这些 classes 提供与基于 JMS 1.1 的对应项相同的功能,但仅依赖于 JMS 1.0.2 API。

39.2.3 连接

ConnectionFactory接口是 JMS 规范的一部分,并作为使用 JMS 的入口点。 Spring 提供ConnectionFactory接口SingleConnectionFactory102的 implementation,基于 JMS 1.0.2 API,您需要设置 boolean property pubSubDomain以指示使用哪个消息传递域,因为SingleConnectionFactory102将始终明确区分javax.jms.QueueConnectionjavax.jmsTopicConnection

39.2.4 Transaction Management

在 JMS 1.0.2 环境中,class JmsTransactionManager102支持管理单个连接工厂的 JMS transactions。有关此功能的更多信息,请参阅JMS Transaction Management上的 reference 文档。

Updated at: 6 months ago
38. Spring Annotation Programming ModelTable of content40. 经典 Spring AOP 用法