1.声明式事务管理
    Spring2.0及以后的版本中声明式事务的配置与之前的版本有相当大的不同。主要差异在于不再需要配置TransactionProxyFactoryBean了。
1.1基于XML Schema
//我们想做成事务性的服务接口
package x.y.service;

public interface FooService {
    Foo getFoo(String fooName);
    Foo getFoo(String fooName, String barName);
    void insertFoo(Foo foo);
    void updateFoo(Foo foo);
}

//上述接口的一个实现
package x.y.service;

public class DefaultFooService implements FooService {
    public Foo getFoo(String fooName) {
        throw new UnsupportedOperationException();
    }
    public Foo getFoo(String fooName, String barName) {
        throw new UnsupportedOperationException();
    }
    public void insertFoo(Foo foo) {
        throw new UnsupportedOperationException();
    }
    public void updateFoo(Foo foo) {
        throw new UnsupportedOperationException();
    }
}
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="
           [url]http://www.springframework.org/schema/beans[/url] [url]http://www.springframework.org/schema/beans/spring-beans-2.0.xsd[/url]
           [url]http://www.springframework.org/schema/tx[/url] [url]http://www.springframework.org/schema/tx/spring-tx-2.0.xsd[/url]
           [url]http://www.springframework.org/schema/aop[/url] [url]http://www.springframework.org/schema/aop/spring-aop-2.0.xsd[/url]">

        <!-- =================================== -->
        <!--                         加载属性文件                        -->
        <!-- =================================== -->
        <bean id="jdbcConfiguration"
            class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="locations">
                <list>
                    <value>classpath:jdbc-config.properties</value>
                </list>
            </property>
        </bean>
        <!-- =================================== -->
        <!--                         配置数据源                          -->
        <!-- =================================== -->
      <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="jdbc.username"/>
        <property name="password" value="${jdbc.password}"/>
      </bean>

      <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
      </bean>

        <!-- =================================== -->
        <!--                         配置事务                            -->
        <!-- =================================== -->
        <aop:config>
            <aop:pointcut id="defaultServiceOperation" expression="execution(* x.y.service.*Service.*(..))"/>
            <aop:advisor pointcut-ref="defaultServiceOperation" advice-ref="defaultTxAdvice"/>
            <aop:pointcut id="noTxServiceOperation" expression="execution(* x.y.service.ddl.DefaultDdlManager.*(..))"/>
            <aop:advisor pointcut-ref="noTxServiceOperation" advice-ref="noTxAdvice"/>
        </aop:config>

        <tx:advice id="defaultTxAdvice" transaction-manager="txManager">
            <tx:attributes>
                <tx:method name="get*" read-only="true"/>
                <tx:method name="*"/>
            </tx:attributes>
        </tx:advice>

        <tx:advice id="noTxAdvice" transaction-manager="txManager">
            <tx:attributes>
                <tx:method name="*" propagation="NEVER"/>
            </tx:attributes>
        </tx:advice>

        <!-- =================================== -->
        <!--                         配置业务Bean                        -->
        <!-- =================================== -->
        <!--
       this bean will be transactional (c.f. the 'defaultServiceOperation' pointcut)
      
-->
        <bean id="fooService" class="x.y.service.DefaultFooService"/>

        <!-- this bean will also be transactional,
           but with totally different transactional settings
-->
        <bean id="anotherFooService" class="x.y.service.ddl.DefaultDdlManager"/>
    </beans>

    更进一步:参照Spring2.0参考手册--9.5.5. <tx:advice/> 有关的设置

1.2使用 @Transactional
    //the service class that we want to make transactional
    @Transactional(readOnly = true)
    public class DefaultFooService implements FooService {

        public Foo getFoo(String fooName) {
            // do something
        }

        // these settings have precedence for this method
        @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
        public void updateFoo(Foo foo) {
            // do something

        }
    }

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="
           [url]http://www.springframework.org/schema/beans[/url] [url]http://www.springframework.org/schema/beans/spring-beans-2.0.xsd[/url]
           [url]http://www.springframework.org/schema/tx[/url] [url]http://www.springframework.org/schema/tx/spring-tx-2.0.xsd[/url]">

        <!-- =================================== -->
        <!--                         加载属性文件                        -->
        <!-- =================================== -->
        <bean id="jdbcConfiguration"
            class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="locations">
                <list>
                    <value>classpath:jdbc-config.properties</value>
                </list>
            </property>
        </bean>

        <!-- =================================== -->
        <!--                         配置数据源                          -->
        <!-- =================================== -->
      <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="jdbc.username"/>
        <property name="password" value="${jdbc.password}"/>
      </bean>

      <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
      </bean>

        <!-- =================================== -->
        <!--                         配置事务                            -->
        <!-- =================================== -->
      <!-- enable the configuration of transactional behavior based on annotations -->
      <tx:annotation-driven transaction-manager="txManager"/>

        <!-- =================================== -->
        <!--                         配置业务Bean                        -->
        <!-- =================================== -->
      <!-- this is the service object that we want to make transactional -->
      <bean id="fooService" class="x.y.service.DefaultFooService"/>
    </beans>


    更进一步:参照Spring2.0参考手册--9.5.6.1. @Transactional 有关的设置

1.3插入事务操作

    1.3.1使用 @Transactional
    <!-- the service class that we want to make transactional -->
    @Transactional(readOnly = true)
    public class DefaultFooService implements FooService {

        public Foo getFoo(String fooName) {
            // do something
        }

        // these settings have precedence for this method
        @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
        public void updateFoo(Foo foo) {
            // do something

        }
    }

package x.y;

import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.util.StopWatch;
import org.springframework.core.Ordered;

public class SimpleProfiler implements Ordered {

    private int order;

    // allows us to control the ordering of advice
    public int getOrder() {
        return this.order;
    }

    public void setOrder(int order) {
        this.order = order;
    }

    // this method is the around advice
    public Object profile(ProceedingJoinPoint call) throws Throwable {
        Object returnValue;
        StopWatch clock = new StopWatch(getClass().getName());
        try {
            clock.start(call.toShortString());
            returnValue = call.proceed();
        } finally {
            clock.stop();
            System.out.println(clock.prettyPrint());
        }
        return returnValue;
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="
   [url]http://www.springframework.org/schema/beans[/url] [url]http://www.springframework.org/schema/beans/spring-beans-2.0.xsd[/url]
   [url]http://www.springframework.org/schema/tx[/url] [url]http://www.springframework.org/schema/tx/spring-tx-2.0.xsd[/url]
   [url]http://www.springframework.org/schema/aop[/url] [url]http://www.springframework.org/schema/aop/spring-aop-2.0.xsd[/url]">

    <bean id="fooService" class="x.y.service.DefaultFooService"/>

    <!-- this is the aspect -->
    <bean id="profiler" class="x.y.SimpleProfiler">
        <!-- execute before the transactional advice (hence the lower order number) -->

        <property name="order" value="1"/>
    </bean>

    <tx:annotation-driven transaction-manager="txManager"/>

    <aop:config>
        <!-- this advice will execute around the transactional advice -->
        <aop:aspect id="profilingAspect" ref="profiler">
            <aop:pointcut id="serviceMethodWithReturnValue" expression="execution(!void x.y..*Service.*(..))"/>
            <aop:around method="profile" pointcut-ref="serviceMethodWithReturnValue"/>
        </aop:aspect>
    </aop:config>

    <!-- other <bean/> definitions such as a DataSource and a PlatformTransactionManager here -->

</beans>

    1.3.2基于XML Schema
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
   [url]http://www.springframework.org/schema/beans[/url] [url]http://www.springframework.org/schema/beans/spring-beans-2.0.xsd[/url]
   [url]http://www.springframework.org/schema/tx[/url] [url]http://www.springframework.org/schema/tx/spring-tx-2.0.xsd[/url]
   [url]http://www.springframework.org/schema/aop[/url] [url]http://www.springframework.org/schema/aop/spring-aop-2.0.xsd[/url]">
    <!--DefaultFooService的代码跟前面一样,只是没有@Transactional注释-->
    <bean id="fooService" class="x.y.service.DefaultFooService"/>

    <!-- the profiling advice -->
    <bean id="profiler" class="x.y.SimpleProfiler">
        <!-- execute before the transactional advice (hence the lower order number) -->
        <property name="order" value="1"/>
    </bean>

    <aop:config>

        <aop:pointcut id="entryPointMethod" expression="execution(* x.y..*Service.*(..))"/>

        <!-- will execute after the profiling advice (c.f. the order attribute) -->

        <aop:advisor advice-ref="txAdvice" pointcut-ref="entryPointMethod" order="2"/>

        <!-- order value is higher than the profiling aspect -->

        <aop:aspect id="profilingAspect" ref="profiler">
            <aop:pointcut id="serviceMethodWithReturnValue" expression="execution(!void x.y..*Service.*(..))"/>
            <aop:around method="profile" pointcut-ref="serviceMethodWithReturnValue"/>
        </aop:aspect>

    </aop:config>

    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="get*" read-only="true"/>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <!-- other <bean/> definitions such as a DataSource and a PlatformTransactionManager here -->

</beans>


1.4Spring1.x版本中声明式事务的配置:
1.4.1配置TransactionProxyFactoryBean
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="baseTxProxy" lazy-init="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
        <property name="transactionManager"><ref bean="transactionManager"/></property>
        <property name="target"><ref bean="daoTarget"/></property>
        <property name="transactionAttributes">
            <props>
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>
    <!-- other <bean/> definitions such as a DataSource and a PlatformTransactionManager here -->
</beans>

1.4.2利用bean继承简化事务代理的配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="baseTxProxy" lazy-init="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
        <property name="transactionManager"><ref bean="transactionManager"/></property>
        <property name="transactionAttributes">
            <props>
                    <prop key="do*">PROPAGATION_REQUIRED</prop>
                    <prop key="get*">PROPAGATION_REQUIRED</prop>
                    <prop key="find*">PROPAGATION_REQUIRED</prop>
                    <prop key="load*">PROPAGATION_REQUIRED</prop>
                    <prop key="update*">PROPAGATION_REQUIRED</prop>
                    <prop key="store*">PROPAGATION_REQUIRED</prop>
                    <prop key="save*">PROPAGATION_REQUIRED</prop>
                    <prop key="delete*">PROPAGATION_REQUIRED</prop>
                    <prop key="print*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>
    <bean id="testTrans1" parent="baseTxProxy">
        <property name="target">
            <bean class="x.y.Test1"/>
        </property>
    </bean>
    <bean id="testTrans2" parent="baseTxProxy">
        <property name="target">
            <bean class="x.y.Test2"/>
        </property>
    </bean>

    <!-- other <bean/> definitions such as a DataSource and a PlatformTransactionManager here -->
</beans>

1.4.3根据BeanName自动创建事务代理
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <!-- 定义BeanNameAutoProxyCreator-->
    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <!--  指定对满足哪些bean name的bean自动生成业务代理 -->
        <property name="beanNames">
            <!--  下面是所有需要自动创建事务代理的bean-->
            <list>
                <value>test1</value>
                <value>test2</value>
            </list>
            <!--  此处可增加其他需要自动创建事务代理的bean-->
        </property>
        <!--  下面定义BeanNameAutoProxyCreator所需的事务拦截器-->
        <property name="interceptorNames">
            <list>
                <value>transactionInterceptor</value>
                    <!-- 此处可增加其他新的Interceptor -->
            </list>
        </property>
    </bean>
    <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
    <!--  事务拦截器bean需要依赖注入一个事务管理器 -->
    <property name="transactionManager" ref="transactionManager"/>
    <property name="transactionAttributes">
        <!--  下面定义事务传播属性-->
        <props>
            <prop key="insert*">PROPAGATION_REQUIRED</prop>
            <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
            <prop key="*">PROPAGATION_REQUIRED</prop>
        </props>
    </property>
    </bean>
    <!-- other <bean/> definitions such as a DataSource and a PlatformTransactionManager here -->
</beans>



2.编程式事务管理
    不建议使用,略。

3.PlatformTransactionManager
使用Spring时,无论你选择编程式还是声明式的事务管理,定义一个正确的 PlatformTransactionManager 实现都是至关重要的。
一般来说,选择PlatformTransactionManager实现时需要知道当前的工作环境,如JDBC、JTA、Hibernate等。

JDBC:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="${jdbc.driverClassName}" />
  <property name="url" value="${jdbc.url}" />
  <property name="username" value="${jdbc.username}" />
  <property name="password" value="${jdbc.password}" />
</bean>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>
</bean>


JTA:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
       [url]http://www.springframework.org/schema/beans[/url] [url]http://www.springframework.org/schema/beans/spring-beans-2.0.xsd[/url]
       [url]http://www.springframework.org/schema/jee[/url] [url]http://www.springframework.org/schema/jee/spring-jee-2.0.xsd[/url]">

  <jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/>

  <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />

  <!-- other <bean/> definitions here -->

</beans>

Hibernate局部事务:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="${jdbc.driverClassName}" />
  <property name="url" value="${jdbc.url}" />
  <property name="username" value="${jdbc.username}" />
  <property name="password" value="${jdbc.password}" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="mappingResources">
    <list>
      <value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
    </list>
  </property>
  <property name="hibernateProperties">
    <value>
      hibernate.dialect=${hibernate.dialect}
    </value>
  </property>
</bean>

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory" ref="sessionFactory" />
</bean>

Hibernate全局事务:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
       [url]http://www.springframework.org/schema/beans[/url] [url]http://www.springframework.org/schema/beans/spring-beans-2.0.xsd[/url]
       [url]http://www.springframework.org/schema/jee[/url] [url]http://www.springframework.org/schema/jee/spring-jee-2.0.xsd[/url]">

  <jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/>
  <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="mappingResources">
      <list>
        <value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
      </list>
    </property>
    <property name="hibernateProperties">
      <value>
        hibernate.dialect=${hibernate.dialect}
      </value>
    </property>
  </bean>

  <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />

  <!-- other <bean/> definitions here -->

</beans>