为不同的 Bean 配置不同的事务语义

考虑这样一种情况:您有许多服务层对象,并且希望对每个对象应用完全不同的事务配置。您可以通过定义具有不同 pointcutadvice-ref 属性值的不同 <aop:advisor/> 元素来实现。

作为比较点,首先假设您所有的服务层类都在根 x.y.service 包中定义。为了使在该包(或子包)中定义且名称以 Service 结尾的所有 bean 都具有默认事务配置,您可以编写以下内容:

<?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="
    http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/tx
    https://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/aop
    https://www.springframework.org/schema/aop/spring-aop.xsd">

  <aop:config>

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

    <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice"/>

  </aop:config>

  <!-- 这两个 bean 将是事务性的... -->
  <bean id="fooService" class="x.y.service.DefaultFooService"/>
  <bean id="barService" class="x.y.service.extras.SimpleBarService"/>

  <!-- ... 而这两个 bean 不会 -->
  <bean id="anotherService" class="org.xyz.SomeService"/> <!-- (不在正确的包中) -->
  <bean id="barManager" class="x.y.service.SimpleBarManager"/> <!-- (不以 'Service' 结尾) -->

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

  <!-- 省略了其他事务基础设施 bean,例如 TransactionManager... -->

</beans>

以下示例显示了如何配置两个具有完全不同事务设置的不同 bean:

<?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="
    http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/tx
    https://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/aop
    https://www.springframework.org/schema/aop/spring-aop.xsd">

  <aop:config>

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

    <aop:pointcut id="noTxServiceOperation"
        expression="execution(* x.y.service.ddl.DefaultDdlManager.*(..))"/>

    <aop:advisor pointcut-ref="defaultServiceOperation" advice-ref="defaultTxAdvice"/>

    <aop:advisor pointcut-ref="noTxServiceOperation" advice-ref="noTxAdvice"/>

  </aop:config>

  <!-- 此 bean 将是事务性的(参见 'defaultServiceOperation' 切入点) -->
  <bean id="fooService" class="x.y.service.DefaultFooService"/>

  <!-- 此 bean 也将是事务性的,但具有完全不同的事务设置 -->
  <bean id="anotherFooService" class="x.y.service.ddl.DefaultDdlManager"/>

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

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

  <!-- 省略了其他事务基础设施 bean,例如 TransactionManager... -->

</beans>