7.6. 简化代理定义

你也许需要许多相似的代理定义,特别是定义事务性代理的时候。使用父子bean定义,以及内部bean定义,可以让代理定义大大得到极大的简化。

首先从父bean开始,为代理bean创建bean定义模版

<bean id="txProxyTemplate" abstract="true"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
  <property name="transactionManager" ref="transactionManager"/>
  <property name="transactionAttributes">
    <props>
      <prop key="*">PROPAGATION_REQUIRED</prop>
    </props>
  </property>
</bean>

这个bean本身将永远不会被初始化,所以实际上是不完整的。而后每个需要创建的代理都是这个bean定义的子bean定义,它们把代理的目标类包装为一个内部bean定义,因为目标对象本身将不会被单独使用。

<bean id="myService" parent="txProxyTemplate">
  <property name="target">
    <bean class="org.springframework.samples.MyServiceImpl">
    </bean>
  </property>
</bean>

当然你可以覆盖从模版中继承的属性,例如在下面这个例子里的事务传播设置:

<bean id="mySpecialService" parent="txProxyTemplate">
  <property name="target">
    <bean class="org.springframework.samples.MySpecialServiceImpl">
    </bean>
  </property>
  <property name="transactionAttributes">
    <props>
      <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
      <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
      <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
      <prop key="store*">PROPAGATION_REQUIRED</prop>
    </props>
  </property>
</bean>

要注意上面例子中我们已经明确地通过设定abstract属性把父bean定义标注为abstract,在前面的章节里有描述,这样它实际上不能被初始化。 缺省情况下应用程序上下文(不仅仅是bean工厂)将预先初始化所有的实例为单例。因此下面这点是很重要的(至少对于单例bean来说),如果你有一个(父)bean定义你希望仅仅作为模版使用,而这个定义说明了一个类,你必须把abstract参数设置为true,否则应用程序上下文将试图预先初始化它。