`
zengbo0710
  • 浏览: 414561 次
社区版块
存档分类
最新评论

Spring声明性事务配置几种方式

阅读更多
 最初使用Spring是为了解决业务层的事务管理问题。原先用手写代码发起、结束/回滚事务的做法碰到粗心的开发者很容易导致连接池的资源耗尽。Spring的声明性事务管理功能无疑是一剂良方。本文说明几种常见的配置方式及各自的优缺点。
方法一:BeanNameAutoProxyCreator
优点:有大量bean声明性事务管理时使用该方法可以简化配置
示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"
>

<beans>

    <description>
        Exploring spring Dependency Injection feature
    </description>
    <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
        <property name="configLocation">
            <value>hibernate.cfg.xml</value>
        </property>
    </bean>
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate.HibernateTransactionManager">
        <property name="sessionFactory">
            <ref local="sessionFactory"/>
        </property>
    </bean>

    <!-- Transaction Interceptor set up to do PROPOGATION_REQUIRED on all methods -->
    <bean id="matchAllTxInterceptor"
        class="org.springframework.transaction.interceptor.TransactionInterceptor">
        <property name="transactionManager">
            <ref bean="transactionManager"/>
        </property>
        <property name="transactionAttributes">
            <props>
                <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>
    <!-- One BeanNameAutoProxyCreator handles all beans where we want all methods to use
    PROPOGATION_REQUIRED -->

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

    <bean id="autoProxyCreator"
        class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="interceptorNames">
            <list>
                <idref local="matchAllTxInterceptor"/>
                <idref bean="hibInterceptor"/>
            </list>
        </property>
        <property name="proxyTargetClass">
            <value>true</value>
        </property>
        <property name="beanNames">
            <list>
                <value>userDocumentManager</value>
            </list>
        </property>
    </bean>

    <bean id="docServerConfig" class="just.docserver.config.DocServerConfig" singleton="true">
        <property name="config"><value>docsrv.conf</value></property>
        <!-- contextPath is which url path the document server resides, KEEP it sync with actual deployment -->
        <property name="contextPath"><value>/axis</value></property>
    </bean>   
    <!--DAO classes definition begin-->
    <bean id="docDao" class="just.docserver.dal.daoimpl.doc.DocDaoImpl">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>   
    <bean id="userFileDao" class="just.docserver.dal.daoimpl.doc.UserFileDaoImpl">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>   
    <bean id="docSettingDao" class="just.docserver.dal.daoimpl.doc.DocSettingDaoImpl">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>   
    <bean id="userDocumentDao" class="just.docserver.dal.daoimpl.doc.UserDocumentDaoImpl">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
        <property name="docDao"><ref local="docDao"/></property>
        <property name="docSettingDao"><ref local="docSettingDao"/></property>
        <property name="userFileDao"><ref local="userFileDao"/></property>
    </bean>   
    <!--DAO classes definition end-->
   

    <!--  Service definition begin -->
    <bean id="userDocumentManager"
        class="just.docserver.UserDocumentManagerImpl"
        singleton="true">
        <property name="docDao"><ref local="docDao"/></property>
        <property name="docSettingDao"><ref local="docSettingDao"/></property>
        <property name="userDocumentDao"><ref local="userDocumentDao"/></property>
        <property name="userFileDao"><ref local="userFileDao"/></property>
        <property name="docServerConfig"><ref local="docServerConfig"/></property>
    </bean>
    <!--  Service definition end -->
</beans>
方法二:TransactionProxyFactoryBean
优点:配置灵活
示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"
>

<beans>

    <description>
        Exploring spring Dependency Injection feature
    </description>
    <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
        <property name="configLocation">
            <value>hibernate.cfg.xml</value>
        </property>
    </bean>
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate.HibernateTransactionManager">
        <property name="sessionFactory">
            <ref local="sessionFactory"/>
        </property>
    </bean>

    <bean id="docServerConfig" class="just.docserver.config.DocServerConfig" singleton="true">
        <property name="config"><value>docsrv.conf</value></property>
        <!-- contextPath is which url path the document server resides, KEEP it sync with actual deployment -->
        <property name="contextPath"><value>/axis</value></property>
    </bean>   
    <!--DAO classes definition begin-->
    <bean id="docDao" class="just.docserver.dal.daoimpl.doc.DocDaoImpl">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>   
    <bean id="userFileDao" class="just.docserver.dal.daoimpl.doc.UserFileDaoImpl">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>   
    <bean id="docSettingDao" class="just.docserver.dal.daoimpl.doc.DocSettingDaoImpl">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>   
    <bean id="userDocumentDao" class="just.docserver.dal.daoimpl.doc.UserDocumentDaoImpl">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
        <property name="docDao"><ref local="docDao"/></property>
        <property name="docSettingDao"><ref local="docSettingDao"/></property>
        <property name="userFileDao"><ref local="userFileDao"/></property>
    </bean>   
    <!--DAO classes definition end-->
   
    <!--  Service definition begin -->
  <bean id="userDocumentManagerTarget" class="just.docserver.UserDocumentManagerImpl">
      <property name="docDao"><ref local="docDao"/></property>
      <property name="docSettingDao"><ref local="docSettingDao"/></property>
      <property name="userDocumentDao"><ref local="userDocumentDao"/></property>
      <property name="userFileDao"><ref local="userFileDao"/></property>
      <property name="docServerConfig"><ref local="docServerConfig"/></property>
  </bean>

    <bean id="userDocumentManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
      <property name="transactionManager">
        <ref local="transactionManager"/>
      </property> 
      <property name="target">
        <ref local="userDocumentManagerTarget"/>
      </property>
      <property name="proxyInterfaces"><value>just.docserver.UserDocumentManager</value></property>
      <property name="transactionAttributes">
        <props>
            <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
            <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
            <prop key="*">PROPAGATION_REQUIRED</prop>
        </props>
      </property>
    </bean>   
    <!--  Service definition end -->
</beans>
但使用该方法配置时需要多配置一个xxxTarget的bean,该bean通常在应用用没有直接的用途,使得配置显得比较累赘。这一问题在高版本的spring中可以用嵌套的bean来解决。也就是将名为xxxTarget的bean直接写道被引用到的地方。按此方法,上例可以改成:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"
>

<beans>

    <description>
        Exploring spring Dependency Injection feature
    </description>
    <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
        <property name="configLocation">
            <value>hibernate.cfg.xml</value>
        </property>
    </bean>
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate.HibernateTransactionManager">
        <property name="sessionFactory">
            <ref local="sessionFactory"/>
        </property>
    </bean>

    <bean id="docServerConfig" class="just.docserver.config.DocServerConfig" singleton="true">
        <property name="config"><value>docsrv.conf</value></property>
        <!-- contextPath is which url path the document server resides, KEEP it sync with actual deployment -->
        <property name="contextPath"><value>/axis</value></property>
    </bean>   
    <!--DAO classes definition begin-->
    <bean id="docDao" class="just.docserver.dal.daoimpl.doc.DocDaoImpl">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>   
    <bean id="userFileDao" class="just.docserver.dal.daoimpl.doc.UserFileDaoImpl">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>   
    <bean id="docSettingDao" class="just.docserver.dal.daoimpl.doc.DocSettingDaoImpl">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>   
    <bean id="userDocumentDao" class="just.docserver.dal.daoimpl.doc.UserDocumentDaoImpl">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
        <property name="docDao"><ref local="docDao"/></property>
        <property name="docSettingDao"><ref local="docSettingDao"/></property>
        <property name="userFileDao"><ref local="userFileDao"/></property>
    </bean>   
    <!--DAO classes definition end-->
   
    <!--  Service definition begin -->
    <bean id="userDocumentManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
      <property name="transactionManager">
        <ref local="transactionManager"/>
      </property> 
      <property name="target">
          <bean class="just.docserver.UserDocumentManagerImpl">
              <property name="docDao"><ref local="docDao"/></property>
              <property name="docSettingDao"><ref local="docSettingDao"/></property>
              <property name="userDocumentDao"><ref local="userDocumentDao"/></property>
              <property name="userFileDao"><ref local="userFileDao"/></property>
              <property name="docServerConfig"><ref local="docServerConfig"/></property>
          </bean>
      </property>
      <property name="proxyInterfaces"><value>just.docserver.UserDocumentManager</value></property>
      <property name="transactionAttributes">
        <props>
            <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
            <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
            <prop key="*">PROPAGATION_REQUIRED</prop>
        </props>
      </property>
    </bean>   
    <!--  Service definition end -->
</beans>
这样整个配置更为简洁清晰,而且更适合于代码生成工具来生成这些配置,进一步提高开发效率。
总结:
本文归纳了Spring声明性事务配置几种方式,BeanNameAutoProxyCreator,TransactionProxyFactoryBean即TransactionProxyFactoryBean加嵌套式Target bean。方法一适用于有大量bean需要声明性事务配置的情形。方法二、三配置更加灵活。方法三比方法二更加简洁、紧凑,十分适用于代码生成。另外,方法有个缺点,如果bean实现某些接口,使用方法一无法指定对这些接口进行截获(利用ProxyFactoryBean的proxyInterfaces属性),从而无法使用JDK的动态代理,只能使用CGLIB来实现方法截获。
 

分享到:
评论

相关推荐

    spring声明式事务配置

    ### 标题解读:Spring声明式事务配置 Spring框架提供了两种主要类型的事务管理方式:编程式事务管理和声明式事务管理。声明式事务管理通过XML配置或注解的形式定义事务边界,使得业务逻辑与事务控制分离。 ### ...

    spring几种事务配置详解【精】

    本文将深入探讨Spring中的几种事务配置方式,帮助开发者更好地理解和运用。 1. **编程式事务管理** 编程式事务管理是在代码中显式调用事务API来控制事务的开始、提交、回滚等操作。这种方式直接在业务逻辑代码中...

    spring声明式事务管理配置方式

    在"spring声明式事务管理配置方式"中,主要涉及到以下几个关键知识点: 1. **Spring事务管理器(Transaction Manager)**: - Spring支持多种事务管理器,如DataSourceTransactionManager(用于JDBC事务)和...

    Spring事务管理的几种配置方式,

    在类上添加`@EnableTransactionManagement`注解开启事务管理,然后使用`@Transactional`注解在方法上声明事务边界。 2. 编程式事务管理 编程式事务管理则需要在代码中显式地调用事务管理API进行控制。这通常通过`...

    Spring 事务 (二) Spring 声明式事务 配置

    本文主要探讨Spring声明式事务管理的配置,这是Spring提供的一种简便的事务管理方式,允许开发者在不编写任何事务管理代码的情况下实现事务控制。这种方式极大地提高了代码的可维护性和可读性。 首先,我们要理解...

    Spring事务原理、Spring事务配置的五种方式

    Spring事务原理是指Spring框架中的一种机制,用于管理事务,并提供了多种配置方式。事务是指一系列的操作,作为一个整体执行,如果其中某个操作失败,整个事务将回滚。Spring事务原理围绕着两个核心:...

    Spring配置的5种方式

    除了上述方式外,还有以下几种事务配置方法: 1. **基于AspectJ的事务配置**: - 使用AspectJ可以更加灵活地配置事务边界,适用于复杂的事务管理场景。 - 示例配置可能涉及`@Aspect`和`@Before`等注解。 2. **...

    Spring事务五种不同的代理配置

    每种事务配置方式都有其适用场景和优缺点。第一种方式需要手动配置事务规则,而第二、三种方式通过注解简化了配置,第四种方式适用于不依赖接口的情况,第五种方式则提供了最大的灵活性。在实际开发中,我们通常会...

    Spring基于XML方式配置事务

    编程式事务管理通过`PlatformTransactionManager`接口及其实现类(如`DataSourceTransactionManager`)进行手动控制,而声明式事务管理则更加简便,通过在XML配置或注解中声明事务边界。 在XML配置中,事务管理主要...

    Spring 事务配置的五种方式.docx

    以下是对Spring事务配置五种方式的详细解释: 1. **基于注解的事务管理(@Transactional)** 使用`@Transactional`注解在类或方法级别声明事务边界。这种方式适用于基于Java的配置,注解可以明确指定事务的传播...

    spring 事务代理配置

    除了使用`TransactionProxyFactoryBean`,Spring还提供了其他几种声明式事务管理配置方式,包括: 1. **使用注解(@Transactional)**:这是最常见的声明式事务管理方式,通过在方法或类上添加`@Transactional`注解...

    spring事务与数据库操作

    ##### 1.2 配置Spring声明式事务 要启用Spring的声明式事务管理,通常需要做以下几步配置: - **配置数据源**:首先需要配置数据源,以便Spring能够访问数据库。 - **配置事务管理器**:接下来,需要配置一个事务...

    spring事务操作试验

    在Spring事务中,有几种常见的隔离级别可供选择,包括读未提交(READ UNCOMMITTED)、读已提交(READ COMMITTED)、可重复读(REPEATABLE READ)和串行化(SERIALIZABLE)。每种隔离级别都有其特定的并发控制策略,...

    spring几种Dao支持配置

    以下将详细阐述Spring对DAO支持的几种配置方式: 1. **JDBC DAO支持:** Spring通过`JdbcTemplate`和`SimpleJdbcInsert`等类提供了对JDBC的抽象,减少了直接使用JDBC代码的繁琐性。`JdbcTemplate`提供了一组模板...

    声明式事务控制spring+hibernate集成

    2. **声明事务边界**:在需要事务控制的方法上添加@Transactional注解,指定事务的传播行为、隔离级别、读写模式等属性。 3. **创建事务代理**:对于需要事务控制的业务服务,使用TransactionProxyFactoryBean创建...

    Spring事务管理Demo

    首先,Spring提供了两种主要的事务管理方式:编程式事务管理和声明式事务管理。 1. **编程式事务管理**:通过使用`PlatformTransactionManager`接口及其实现类(如`JdbcTemplate`或`HibernateTemplate`),开发者...

    spring2.0声明式事务

    ### Spring 2.0 声明式事务配置详解 #### 一、Spring 2.0 声明式事务概述 随着 Spring 框架的发展,从 Spring 1.x 到 Spring 2.0 版本,声明式事务管理方式有了显著改进。在 Spring 1.x 中,主要通过 AOP 方式实现...

    spring事务与配置

    以上介绍了Spring中事务配置的五种方式,每种方式都有其适用场景和特点。选择合适的事务配置方式可以帮助我们更好地管理和控制应用中的事务,提高系统的稳定性和可维护性。在实际项目开发中,可以根据项目的具体情况...

    Spring 2.5整合iBATIS 2.3并使用Spring的声明式事务管理

    本篇将详细介绍如何在Spring 2.5版本中整合iBATIS 2.3,并利用Spring的声明式事务管理,以提升应用程序的稳定性和可维护性。 首先,我们需要了解Spring 2.5和iBATIS 2.3的基本概念。Spring 2.5是Spring框架的一个...

Global site tag (gtag.js) - Google Analytics