39. 经典 spring 用法

本附录讨论了一些经典的Spring使用模式,作为维护传统Spring应用程序的开发人员的参考。这些使用模式不再反映使用这些功能的推荐方式,当前推荐的用法将在参考手册的相应章节中介绍。

39.1 经典ORM用法

本节介绍了在旧版Spring应用程序中可能遇到的经典使用模式。有关当前推荐的使用模式,请参阅 ORM 章节。

39.1.1 休眠

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

HibernateTemplate

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

<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 类提供了许多镜像Hibernate Session 接口上公开的方法的方法,以及许多方便的方法,例如上面显示的方法。如果您需要访问 Session 以调用 HibernateTemplate 上未公开的方法,您可以始终下拉到基于回调的方法,如下所示。

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();
            }
        };
    }

}

有效的回调实现可用于任何Hibernate数据访问。 HibernateTemplate 将确保 Session 实例正确打开和关闭,并自动参与 Transaction 。模板实例是线程安全且可重用的,因此可以将它们保存为周围类的实例变量。对于简单的单步操作(如单个查找,加载,saveOrUpdate或删除调用), HibernateTemplate 提供了可替代此类一行回调实现的替代便捷方法。此外,Spring提供了一个方便的 HibernateDaoSupport 基类,它提供了一个 setSessionFactory(..) 方法来接收 SessionFactorygetSessionFactory()getHibernateTemplate() 供子类使用。结合使用,这可以实现非常简单的DAO实现,满足典型要求:

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的DAO

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

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访问代码的优点是它允许在数据访问代码中抛出任何已检查的应用程序异常;将此与 HibernateTemplate 类进行对比,该类仅限于在回调中仅抛出未经检查的异常。请注意,您通常可以在回调之后推迟相应的检查和抛出应用程序异常,这仍然允许使用 HibernateTemplate 。通常, HibernateTemplate 类的便捷方法对于许多场景来说更简单,更方便。

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的类。本节介绍Spring JMS对JMS 1.0.2弃用类的支持。


Domain Unification

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

JMS 1.0.2定义了两种类型的消息传递域,点对点(队列)和发布/订阅(主题)。 1.0.2 API通过为每个域提供并行类层次结构来反映这两个消息传递域。因此,客户端应用程序在使用JMS API时变得特定于域。 JMS 1.1引入了域统一的概念,最大限度地减少了两个域之间的功能差异和客户端API差异。作为已删除的功能差异的示例,如果使用JMS 1.1提供程序,则可以从事务上使用来自一个域的消息并生成消息另一方面使用相同的 Session

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


39.2.1 JmsTemplate

位于 org.springframework.jms.core 包中的类 JmsTemplate102 提供了 JmsTemplate 描述JMS章节的所有功能,但它基于JMS 1.0.2 API而不是JMS 1.1 API。因此,如果您使用的是JmsTemplate102,则需要设置布尔属性 pubSubDomain 以配置 JmsTemplate ,并了解正在使用的JMS域。默认情况下,此属性的值为false,表示将使用点对点域Queues。

39.2.2 异步消息接收

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

39.2.3 连接

ConnectionFactory 接口是JMS规范的一部分,并作为使用JMS的入口点。 Spring提供了 ConnectionFactory 接口的实现, SingleConnectionFactory102 ,基于JMS 1.0.2 API,它将在所有 createConnection() 调用上返回相同的 Connection 并忽略对 close() 的调用。您需要设置布尔属性 pubSubDomain 以指示使用哪个消息传递域,因为 SingleConnectionFactory102 将始终明确区分 javax.jms.QueueConnectionjavax.jmsTopicConnection

39.2.4 Transaction 管理

在JMS 1.0.2环境中,类 JmsTransactionManager102 为管理单个连接工厂的JMS事务提供支持。有关此功能的更多信息,请参阅 JMS Transaction Management 上的参考文档。

Updated at: 5 months ago
38. Spring注释编程模型Table of content40. Classic Spring AOP用法
Comment
You are not logged in.

There are no comments.