spring 事务

论坛 期权论坛     
选择匿名的用户   2021-5-30 02:14   562   0
<p> </p>
<p>平时我们都是使用注解开启事务&#64;EnableTransactionManagement</p>
<pre class="blockcode"><code>&#64;Target(ElementType.TYPE)
&#64;Retention(RetentionPolicy.RUNTIME)
&#64;Documented
&#64;Import(TransactionManagementConfigurationSelector.class)
public &#64;interface EnableTransactionManagement {


//proxyTargetClass &#61; false表示是JDK动态代理支持接口代理。true表示是Cglib代理支持子类继承代理。
boolean proxyTargetClass() default false;

//事务通知模式(切面织入方式),默认代理模式(同一个类中方法互相调用拦截器不会生效),可以选择增强型AspectJ
AdviceMode mode() default AdviceMode.PROXY;

//连接点上有多个通知时,排序,默认最低。值越大优先级越低。
int order() default Ordered.LOWEST_PRECEDENCE;
}
</code></pre>
<p>重点看类注解&#64;Import(TransactionManagementConfigurationSelector.class)</p>
<p> </p>
<pre class="blockcode"><code>public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector&lt;EnableTransactionManagement&gt; {

   /**
    * Returns {&#64;link ProxyTransactionManagementConfiguration} or
    * {&#64;code AspectJ(Jta)TransactionManagementConfiguration} for {&#64;code PROXY}
    * and {&#64;code ASPECTJ} values of {&#64;link EnableTransactionManagement#mode()},
    * respectively.
    */
   &#64;Override
   protected String[] selectImports(AdviceMode adviceMode) {
      switch (adviceMode) {
         case PROXY:
            // 向Spring中添加了AutoProxyRegistrar和ProxyTransactionManagementConfiguration对应的bean
            return new String[] {AutoProxyRegistrar.class.getName(),
                  ProxyTransactionManagementConfiguration.class.getName()};
         case ASPECTJ:
            // 不考虑
            return new String[] {determineTransactionAspectClass()};
         default:
            return null;
      }
   }

   private String determineTransactionAspectClass() {
      return (ClassUtils.isPresent(&#34;javax.transaction.Transactional&#34;, getClass().getClassLoader()) ?
            TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
            TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
   }

}
</code></pre>
<p> </p>
<p>最终会执行selectImports方法导入需要加载的类,我们只看proxy模式下,载入了AutoProxyRegistrar、ProxyTransactionManagementConfiguration2个类。</p>
<ul><li>AutoProxyRegistrar:<code>给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件;利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;</code></li><li>ProxyTransactionManagementConfiguration:就是一个配置类,定义了事务增强器。</li></ul>
<p> </p>
<p> </p>
<p><strong>AutoProxyRegistrar</strong></p>
<p>先看AutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,复写registerBeanDefinitions方法,源码如下:</p>
<pre class="blockcode"><code>public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

private final Log logger &#61; LogFactory.getLog(getClass());

/**
  * Register, escalate, and configure the standard auto proxy creator (APC) against the
  * given registry. Works by finding the nearest annotation declared on the importing
  * {&#64;code &#64;Configuration} class that has both {&#64;code mode} and {&#64;code proxyTargetClass}
  * attributes. If {&#64;code mode} is set to {&#64;code PROXY}, the APC is registered; if
  * {&#64;code proxyTargetClass} is set to {&#64;code true}, then the APC is forced to use
  * subclass (CGLIB) proxying.
  * &lt;p&gt;Several {&#64;code &#64;Enable*} annotations expose both {&#64;code mode} and
  * {&#64;code proxyTargetClass} attributes. It is important to note that most of these
  * capabilities end up sharing a {&#64;linkplain AopConfigUtils#AUTO_PROXY_CREATOR_BEAN_NAME
  * single APC}. For this reason, this implementation doesn&#39;t &#34;care&#34; exactly which
  * annotation it finds -- as long as it exposes the right {&#64;code mode} and
  * {&#64;code proxyTargetClass} attributes, the APC can be registered and configured all
  * the same.
  */
&#64;Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  boolean candidateFound &#61; false;
  Set&lt;String&gt; annTypes &#61; importingClassMetadata.getAnnotationTypes();
  for (String annType : annTypes) {
   // 获取EnableTransactionManagement注解的属性值
   AnnotationAttributes candidate &#61; AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
   if (candidate &#61;&#61; null) {
    continue;
   }
   Object mode &#61; candidate.get(&#34;mode&#34;);
   Object proxyTargetClass &#61; candidate.get(&#34;proxyTargetClass&#34;);
   if (mode !&#61; null &amp;&amp; proxyTargetClass !&#61; null &amp;&amp; AdviceMode.class &#61;&#61; mode.getClass() &amp;&amp;
     Boolean.class &#61;&#61; proxyTargetClass.getClass()) {
    candidateFound &#61; true;
    if (mode &#61;&#61; AdviceMode.PROXY) {
     // 注册一个InfrastructureAdvisorAutoProxyCreator类型的Bean
     AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
     if ((Boolean) proxyTargetClass) {
      AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
      return;
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP