[Spring]Spring AOP源码解析

404 阅读8分钟

对于Spring Aop, 可以从三个方面进行解析.

1. Spring配置文件或者@AspectJ主角中的Aop配置如何被解析? Advisor

Spring Aop是使用动态代理来实现的,即将Aspect(切面)的内容织入动态代理类中: xx$Proxy

那么就有2个疑问:

2. Spring Aop要生成动态代理类$Proxy, 是怎么参与到BeanFactory.getBean(beanName)中的流程的? getBean()中是根据beanDefinition来加载Class<?>,并生成对应的类实例的.

Spring要想实现Aop,那么生成的实例就应该是动态代理类$Proxy的实例.而不是原始类的实例.

3. Spring Aop中具体是怎么生成动态代理类$Proxy的? Jdk 动态代理和Cglib动态代理都是怎么参与进来的: Spring Aop动态代理具体实现过程. 

Spring Aop配置如何被解析? 

在Spring中关于Aop的配置有spring xml和注解2种方式进行配置,先看spring xml配置的方式如何解析. 这个看起来比较简单一点.

<aop:config>
     <aop:pointcut expression="execution(public *com.briup.aop.service.*.*(..))" id="myPointCut"/>
     <aop:aspect id='aspect' ref='切面bean'>
         <aop:before method='切面bean中的方法' pointcut-ref='切点ref'/>
         <aop:after method='xx' pointcut-ref='xxRef'/>
     </aop:aspect>
     <aop:advisor advisor-ref='adviceBean' pointcut-ref='pointcutDefinition'/>
</aop:config>

 通过阅读Spring读取xml得到BeanDefinition的源码可以得到, 关于xml配置的解析都是NamespaceHandler的实现类来完成的.  

在AopNamespanceHanlder中完成了对aop:xxx 命名空间下的配置解析. 

@Override
public void init() {
   // In 2.0 XSD as well as in 2.1 XSD.
   registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
   registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
   registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

   // Only in 2.0 XSD: moved to context namespace as of 2.1
   registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}

可以看到aop:config下的配置都是用ConfigBeanDefinitionParser实例来解析的.

在ConfigBeanDefinitionParser中有parsePointcut, parseAdvisor , parseAspect方法来解析aop:config中的配置.

最终会得到pointcutBeanDefinition, adviceBeanDefinition, advisorBeanDefinition. 得到的beanDefinition会注册到BeanDefinitionRegistry: beanFactory中. 这样在getBean()的时候就可以从beanFactory中获取到Aop配置相关的beanDefitnion.

具体的解析过程参考:[Spring ConfigBeanDefinitionParse源码解析] ,在这篇文章中只描述各个组件之间的关系. 

Spring Aop是如何参与到getBean的流程

在Spring ConfigBeanDefinitionParser中有这样一段代码: (也是看了好久,一直还不知道是干什么的)

configureAutoProxyCreator(parserContext, element)

追根溯源AopNamespaceUtils -> AopConfigUtils, 最终发现是向beanFacotry:BeanDefinitionRegistry中注册了一个

beanName: ‘org.springframework.aop.config.internalAutoProxyCreator’

beanClass: AspectJAwareAdvisorAutoProxyCreator

的beanDefinition. 

查看AspectJAwareAdvisorAutoProxyCreator的类图, 可以看到它实现了SmartInstantiationAwareBeanPostProcessor. 

 既然知道了它实现了SmartInstantiationAwareBeanPostProcessor, 那么就知道了它肯定会参与到beanFactory.getBean()的流程中: 在getBean()提供了一系列的Hook.

参考文章: [Spring AbstractBeanFacotyr.getBean流程]

Haha,这里就知道了上面注册的AspectJAwareAdvisorAutoProxyCreator是干什么的了,就是为了参与到Spring getBean()的流程来创建Aespect切入的bean. 

AbstractAutoProxyCreator: 通过实现SmartInstantiationAwareBeanPostProcessor: postProcessBeforInstantiation 参与到getBean()中创建bean instance的流程中来. 

	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
		if (beanName != null) {
			TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
			if (targetSource != null) {
				this.targetSourcedBeans.add(beanName);
				Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
				Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
				this.proxyTypes.put(cacheKey, proxy.getClass());
				return proxy;
			}
		}

		return null;
	}

在AbstractAutoProxyCreator中就描述了怎么生成Aop切面切入之后的proxy bean instance.

AbstractAutoProxyCreator.getAdvicesAndAdvisorsForBean(beanClass,beanName,targetSource): 用来获取bean需要切入的切面.

AbstractAutroProxyCreator.createProxy(beanClass, beanName, specificInterceptors,targetSource): 描述了如何根据advisor来构建proxy instance

AbstractAutoProxyCreator定义了一套模板, 具体getAdvicesAndAdvisorsForBean的过程在子类AbstractAdvisorAutoProxyCreator中被实现.

AbstractAdvisorAutoProxyCreator:

@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
   List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
   if (advisors.isEmpty()) {
      return DO_NOT_PROXY;
   }
   return advisors.toArray();
}protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
   List<Advisor> candidateAdvisors = findCandidateAdvisors();
   List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
   extendAdvisors(eligibleAdvisors);
   if (!eligibleAdvisors.isEmpty()) {
      eligibleAdvisors = sortAdvisors(eligibleAdvisors);
   }
   return eligibleAdvisors;
} protected List<Advisor> findCandidateAdvisors() {
   return this.advisorRetrievalHelper.findAdvisorBeans();
}

最终findCandidateAdvisors的实现委托给了advisorRetrievalHelper.findAdvisorBeans(). 

/**
 * Find all eligible Advisor beans in the current bean factory,
 * ignoring FactoryBeans and excluding beans that are currently in creation.
 * @return the list of {@link org.springframework.aop.Advisor} beans
 * @see #isEligibleBean
 */
public List<Advisor> findAdvisorBeans() {
   // Determine list of advisor bean names, if not cached already.
   String[] advisorNames = null;
   synchronized (this) {
      advisorNames = this.cachedAdvisorBeanNames;
      if (advisorNames == null) {
         // Do not initialize FactoryBeans here: We need to leave all regular beans
         // uninitialized to let the auto-proxy creator apply to them!
         advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
               this.beanFactory, Advisor.class, true, false);
         this.cachedAdvisorBeanNames = advisorNames;
      }
   }
   if (advisorNames.length == 0) {
      return new LinkedList<Advisor>();
   }

   List<Advisor> advisors = new LinkedList<Advisor>();
   for (String name : advisorNames) {
      if (isEligibleBean(name)) {
         if (this.beanFactory.isCurrentlyInCreation(name)) {
            if (logger.isDebugEnabled()) {
               logger.debug("Skipping currently created advisor '" + name + "'");
            }
         }
         else {
            try {
               advisors.add(this.beanFactory.getBean(name, Advisor.class));
            }
            catch (BeanCreationException ex) {
               Throwable rootCause = ex.getMostSpecificCause();
               if (rootCause instanceof BeanCurrentlyInCreationException) {
                  BeanCreationException bce = (BeanCreationException) rootCause;
                  if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {
                     if (logger.isDebugEnabled()) {
                        logger.debug("Skipping advisor '" + name +
                              "' with dependency on currently created bean: " + ex.getMessage());
                     }
                     // Ignore: indicates a reference back to the bean we're trying to advise.
                     // We want to find advisors other than the currently created bean itself.
                     continue;
                  }
               }
               throw ex;
            }
         }
      }
   }
   return advisors;
}

通过BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans()中的这句代码:

BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);

可以知道, findAdvisor的过程也是从beanFactory:BeanDefinitionRegistry中获取Advisor的BeanDefiniton, 然后getBean().

这里也和前面ConfigBeanDefinitionParser中将Adviso 的BeanDefinition注册到beanFactory:BeanDefinitionRegistry的过程联系起来.

AbstractAdvisorAutoProxyCreator在findCandidateAdvisors后, 会判断哪些advisor可以切入到beanClass中.

findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); 就是判断哪些advisor可以应用到beanClass的.

具体是如何判断是否可以应用的,后面再描述

FAQ:

1. 关于类图中

AspectJAwareAdvisorAutoProxyCreator,

AnnotationAwareAspectJAutoProxyCreator

InfrastructureAdvisorAutoProxyCreator

之间的关系. ??

Answer:

在AopConfigUtils中,定义了一个优先级列表:

private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<Class<?>>();

/**
 * Setup the escalation list.
 */
static {
   APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
   APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
   APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}

在注册AutoProxyCreator实例的时候优先级高的会替换优先级低的注册到beanFactor:BeanDefinitionRegistry中.

public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
   return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
}private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
   if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
      BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
      if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
         int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
         int requiredPriority = findPriorityForClass(cls);
         if (currentPriority < requiredPriority) {
            apcDefinition.setBeanClassName(cls.getName());
         }
      }
      return null;
   }
   RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
   beanDefinition.setSource(source);
   beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
   beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
   registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
   return beanDefinition;
}

AnnotationAwareAspectJAutoProxyCreator比AspectJAwareAdvisorAutoProxyCreatory优先级高.

AnnotationAwareAspectJAutoProxyCreator是AspectJAwareAdvisorAutoProxyCreatory的子类.

在AnnotationAwareAspectJAutoProxyCreator中,覆盖实现了findCandidateAdvisors方法:

@Override
protected List<Advisor> findCandidateAdvisors() {
   // Add all the Spring advisors found according to superclass rules.
   List<Advisor> advisors = super.findCandidateAdvisors();
   // Build Advisors for all AspectJ aspects in the bean factory.
   advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
   return advisors;
}

在aspectJAdvisorsBuilder.buildAspectJAdvisors()中解析了@AspectJ中配置的Aop配置.

AnnotationAwareAspectJAutoProxyCreator不仅具有了AspectJAwareAdvisorAutoProxyCreator的功能,还解析了@AspectJ配置的Aop, 构建了Advisor.

AnnotationAwareAspectJAutoProxyCreator在AspectJAutoProxyBeanDefinitionParser中被注册. 

lass AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
   @Override
   public BeanDefinition parse(Element element, ParserContext parserContext) {
      AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
      extendBeanDefinition(element, parserContext);
      return null;
   }

在AspectJAutoProxyBeanDefinitionParser中不负责解析工作,真正的解析工作都放到AnnotationAwareAspectJAutoProxyCreator中实现, 委托给aspectJAdvisorsBuilder.

Spring Aop在创建Proxy的时候是怎么实现的?

现在已经有了Advisor, 下面就是怎么创建proxy instance的过程了.

在AbstractAutoProxyCreator中可以看到是在createProxy()中完成对Aop proxy instance的创建. AbstractAutoProxyCreator.createProxy():

protected Object createProxy(Class<?> beanClass, String beanName, Object[]
specificInterceptors, TargetSource targetSource) {

   ProxyFactory proxyFactory = new ProxyFactory();
   proxyFactory.copyFrom(this);
   if (!proxyFactory.isProxyTargetClass()){
      if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
      }else {
         evaluateProxyInterfaces(beanClass, proxyFactory);
      }
   }
   Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
   for (Advisor advisor :advisors) {
      proxyFactory.addAdvisor(advisor);
   }
   proxyFactory.setTargetSource(targetSource);
   customizeProxyFactory(proxyFactory);
   proxyFactory.setFrozen(this.freezeProxy);
   if (advisorsPreFiltered()){
      proxyFactory.setPreFiltered(true);
   }

   return proxyFactory.getProxy(getProxyClassLoader());
}

通过阅读上面的代码可以发现是通过ProxyFactory实例来创建proxy instance的.

这里我们先看看ProxyFactory的类图:(因为发现ProxyFactory并不是一个简单的工厂)

通过阅读上面的源码AbstractAutoProxyCreator.createProxy()和对ProxyFactory整个类图的理解.可以知道Aop proxy instance的创建过程是通过AopProxy类来完成的.

在使用ProxyFactory.geteProxy()的时候, 使用的是默认的DefaultAopProxyFactory来创建的AopProxy实例. (ProxyFactory extends ProxyCreatorSupport . ProxyCreatorSupport默认使用的DeafultAopProxyFactory).

那么我们再来看看是怎么创建AopProxy的.

在ProxyCreatorSupport中

protected final synchronized AopProxy createAopProxy() {
   if (!this.active) {
      activate();
   }
   return getAopProxyFactory().createAopProxy(this);
}

上面getAopProxyFactory()就获得默认的DefaultAopProxyFactory或者自定义AopProxyFactory.

使用getAopProxyFactory().createAopProxy(this)来创建Aopproxy, 是因为该类还兼职了AdvisedSupport功能.

DefaultAopProxyFactory.createAopProxy(AdvisedSupport config):

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException{    if (config.isOptimize() || config.isProxyTargetClass() 
             || hasNoUserSuppliedProxyInterfaces(config)) {
      Class<?> targetClass =config.getTargetClass();
      if (targetClass == null) {
         throw new AopConfigException("TargetSourcecannot determine target class: " +               "Either an interface or a target is required for proxy creation.");
      }
      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
         return new JdkDynamicAopProxy(config);
      }
      return new ObjenesisCglibAopProxy(config);
   }   else {
      return new JdkDynamicAopProxy(config);
   }
}

阅读上面DefaultAopProxyFactory.createAopProxy(AdvisedSupport config)可以看到是根据不同的配置来选择创建不同的AopProxy类实例.

?? 网上说的optimize=’true’的智能优化策略在哪里?? 我只看出来了如果目标类是接口或者是通过Proxy.newProxyInstance创建的jdk代理类则继续使用JdkDynamicAopProxy.

Answer: TODO

这里的AopProxy为Spring framework提供了统一的创建proxy instance的接口:

+ getProxy()

+ getProxy(classLoader)

有通过jdk动态代理来实现JdkDynamicAopProxy; 也用通过Cglib代理技术来实现的CglibAopProxy/ObjenesisCglibAopProxy.

Ps: 这里的ObjenesisCglibAopProxy是采用了Objenesis技术: Obenesis是弥补jdk不足而创造的. Class.newInstnce贼没有午餐构造函数是不能生成对象的,这里objenesis就可以派上用场. (这个只是其中一点)具体的关于Objenesis在后面进行描述.

Objenesis在Spring 4.0+中被引入

JdkDynamicAopProxy和ObjenesisCglibAopProxy/CglibAopProxy在

DefaultAopProxyFactory中被创建. (上文中提到的代码已经描述过)

JdkDynamicAopProxy:

@Override
public Object getProxy() {
   return getProxy(ClassUtils.getDefaultClassLoader());
}
@Override
public Object getProxy(ClassLoader classLoader) {
   if (logger.isDebugEnabled()){
      logger.debug("Creating JDK dynamic proxy: target source is " 
        + this.advised.getTargetSource());
   }
   Class<?>[] proxiedInterfaces =AopProxyUtils.completeProxiedInterfaces(this.advised);
   findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
   return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

可以看到在JdkDynamicAopProxyFactory中是使用的java.lang.reflect.Proxy 来完成对proxy instance的创建的.

通过还看到JdkDynamicAopProxyFactory实现了InvocationHandler接口: 这里是jdk Proxy需要的.

CglibAopProxyFactory:

@Override
public Object getProxy() {
   return getProxy(null);
}

@Override
public Object getProxy(ClassLoader classLoader) {
   if (logger.isDebugEnabled()) {
      logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
   }

   try {
      Class<?> rootClass = this.advised.getTargetClass();
      Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

      Class<?> proxySuperClass = rootClass;
      if (ClassUtils.isCglibProxyClass(rootClass)) {
         proxySuperClass = rootClass.getSuperclass();
         Class<?>[] additionalInterfaces = rootClass.getInterfaces();
         for (Class<?> additionalInterface : additionalInterfaces) {
            this.advised.addInterface(additionalInterface);
         }
      }

      // Validate the class, writing log messages as necessary.
      validateClassIfNecessary(proxySuperClass, classLoader);

      // Configure CGLIB Enhancer...
      Enhancer enhancer = createEnhancer();
      if (classLoader != null) {
         enhancer.setClassLoader(classLoader);
         if (classLoader instanceof SmartClassLoader &&
               ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
            enhancer.setUseCache(false);
         }
      }
      enhancer.setSuperclass(proxySuperClass);
      enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
      enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
      enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));

      Callback[] callbacks = getCallbacks(rootClass);
      Class<?>[] types = new Class<?>[callbacks.length];
      for (int x = 0; x < types.length; x++) {
         types[x] = callbacks[x].getClass();
      }
      // fixedInterceptorMap only populated at this point, after getCallbacks call above
      enhancer.setCallbackFilter(new ProxyCallbackFilter(
            this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
      enhancer.setCallbackTypes(types);

      // Generate the proxy class and create a proxy instance.
      return createProxyClassAndInstance(enhancer, callbacks);
   }
   catch (CodeGenerationException ex) {
      throw new AopConfigException("Could not generate CGLIB subclass of class [" +
            this.advised.getTargetClass() + "]: " +
            "Common causes of this problem include using a final class or a non-visible class",
            ex);
   }
   catch (IllegalArgumentException ex) {
      throw new AopConfigException("Could not generate CGLIB subclass of class [" +
            this.advised.getTargetClass() + "]: " +
            "Common causes of this problem include using a final class or a non-visible class",
            ex);
   }
   catch (Exception ex) {
      // TargetSource.getTarget() failed
      throw new AopConfigException("Unexpected AOP exception", ex);
   }
}

上面的代码中也可以看到在CglibAopProxy中是使用了

org.springframework.cglib.proxy.Enhancer 来创建的proxy instance. 

到这里,关于Spring AOP的相关的疑问就已经解答完了. 如果有新的疑问也可以和我沟通.

上面已经对Spring AOP有了深刻的认知,那么下面就对Spring中比较经典的AOP应用案例:

Spring Aop: tx:事务解读一下.

Spring AOP tx:事务相关配置如何被解析的

通过前面的阅读Spring AOP的配置是如何被解析的: aop:xxx 命名空间是被AopNamespaceHandler解读的. 那么可以知道tx:xxx命名空间是被TxNamespaceHandler解读的.

Spring中关于事务的配置:

<bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager"
        abstract="false" lazy-init="default" autowire="default"
        dependency-check="default">
        <property name="sessionFactory">
            <ref bean="sessionFactory" />
        </property>
    </bean>
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="delete*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="add*" propagation="REQUIRED" />
            <!-- <tx:method name="*" propagation="true" />-->
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:pointcut id="allManagerMethod"
            expression="execution(* com.service.*.*(..))" />
        <aop:advisor advice-ref="txAdvice"
            pointcut-ref="allManagerMethod" />
    </aop:config>

TxNamespaceHandler:

@Override
public void init() {
   registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
   registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
   registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
}

可以看到tx:advice是被TxAdviceBeanDefinitionParser解析的.

<tx: annotation-driven>是用来处理注解事务@Transactional的, 这里暂时不用讨论,大同小异. 和@Pointcut差不太多. 先了解XML配置是如何解析的,后面注解式的解析只是解析方式不一样而已.

tx:jta-transacation-manager是用来解析分布式事务相关的,一般的情况下也用到到分布式事务. 后面有空在对这方面进行解析.

Spring AOP非tx:命名空间的声明式事务解析

在阅读tx:xxx配置方式配置事务的时候,发现了另外一种Spring声明式事务配置的方式:

<bean 
id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
     abstract="true">
    <property name="transactionManager" ref="transactionManager"/>
    <property name="transactionAttributes">
      <props>
        <prop key="insert*">PROPAGATION_REQUIRED</prop>
        <prop key="update*">PROPAGATION_REQUIRED</prop>
        <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
      </props>
    </property>
  </bean>
 
  <bean id="myProxy" parent="baseTransactionProxy">
    <property name="target" ref="myTarget"/>
  </bean>
 
 <bean id="yourProxy" parent="baseTransactionProxy">
   <property name="target" ref="yourTarget"/>
  </bean>

 这里是TransactionProxyFactoryBean进行处理的