(三)Springソース分析----tx事務管理

9608 ワード

Spring事務はAOP代理に基づいて完成しました.前のAOPソース分析の基礎があります.Spring事務は分かりやすいです.まずSpringの注釈版の事務配置例を見てみます.
Spring設定クラス:AOP機能を開くと同じように、事務機能も注釈@EnbaleTransaction Managementで開く必要があります.また、事務マネージャを配置する必要があります.デフォルトではDataSourceTransationManager事務管理器を使用します.
@ComponentScan("ts")
@EnableTransactionManagement
@EnableAspectJAutoProxy
@Configurable
public class TsConfig {
    
    //      
    @Bean
    public DataSource dataSource()throws Exception{
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser("root");
        dataSource.setPassword("w4467106");
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setConnectionCustomizerClassName(YourConnectionCustomizer.class.getName());
        return dataSource;
    }
    
    //            
    @Bean
    public JdbcTemplate jdbcTemplate()throws Exception{
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());

        return jdbcTemplate;

    }
    //        
    @Bean
    public PlatformTransactionManager transactionManager()throws Exception{
        return new DataSourceTransactionManager(dataSource());
    }
}
ここに穴があります.インターネットで事務を配置した後、異常が発生したことを発見しました.MysqlエンジンもInnoDBです.最終的にはc 3 p 0のカバンの中のCoboPooledDataSourceデータソースが発見されました.デフォルトのComplodDataSourceデータソースはオープン前にデータベース接続の自動提出をオフしません.AbstractConnection Custoomizer類を引き継ぎ、データベース接続を自動的にオフにする必要があります.
public class YourConnectionCustomizer extends AbstractConnectionCustomizer {

    @Override
    public void onCheckOut(Connection c, String parentDataSourceIdentityToken) throws Exception {
        super.onCheckOut(c, parentDataSourceIdentityToken);
        c.setAutoCommit(false);
    }
}
ところで、Spring事務の原理を探ってみます.事務をオープンします.@EnbaleTranscationManagementをクリックしてみると、AOPとはセットです.全部Importを通してSpringコンポーネントを導入して、期待機能を完成します.
//   TransactionManagementConfigurationSelector  
@Import({TransactionManagementConfigurationSelector.class})
public @interface EnableTransactionManagement {
    boolean proxyTargetClass() default false;

    AdviceMode mode() default AdviceMode.PROXY;

    int order() default 2147483647;
}
Transation Management ConfigrationSelectorコンポーネントはどのような機能を果たしていますか?ソースからSelectorを発見しました.また、2つの新しいコンポーネントAutoProxyRegistarとProxTranction Management Configrationを登録してくれました.この2つのコンポーネントの役割を分析します.
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector {
    public TransactionManagementConfigurationSelector() {
    }

    protected String[] selectImports(AdviceMode adviceMode) {
        switch(adviceMode) {
        case PROXY:
             //   adviceMode     ,              
            return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
        case ASPECTJ:
            return new String[]{"org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration"};
        default:
            return null;
        }
    }
}
AutoProxyRegistar:実は、その役割は容器に後置プロセッサを登録し、後置プロセッサ機構を利用してbeanに包装代理オブジェクトを作成し、増強器advisorを追加することです.
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    private final Log logger = LogFactory.getLog(this.getClass());
    
    ............................
    //  AOP  ,      AopConfigUtils              
    AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
    .........
}

//          
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
        return registerOrEscalateApcAsRequire(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
    }

...............

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
......................


   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean != null) {
            Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                //     AOP   bean           
                return this.wrapIfNecessary(bean, beanName, cacheKey);
            }
        }

        return bean;
    }

}

             ProxyTranction Management Configration:その役割は主に容器に事務増長器advisorを作成することであり、第一歩は増長器に事務属性リソースtransplation AttributeSourceを追加し、第二ステップは増長器に事務ブロックを追加することである.
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    public ProxyTransactionManagementConfiguration() {
    }
    
    //        
    @Bean(
        name = {"org.springframework.transaction.config.internalTransactionAdvisor"}
    )
    @Role(2)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
        //          
        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        //              
        advisor.setTransactionAttributeSource(this.transactionAttributeSource());
        //        
        advisor.setAdvice(this.transactionInterceptor());
        advisor.setOrder((Integer)this.enableTx.getNumber("order"));
        return advisor;
    }

}
第1段階で追加されたトランザクション属性リソース解析器Advisor()は、トランザクション解析用のTrantationTransationAttributeSource()を登録します.
public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource();
    }

.........................................................
  //     SpringTransactionAnnotationParser                
  protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
        RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
        Propagation propagation = (Propagation)attributes.getEnum("propagation");
        rbta.setPropagationBehavior(propagation.value());
        Isolation isolation = (Isolation)attributes.getEnum("isolation");
        rbta.setIsolationLevel(isolation.value());
        rbta.setTimeout(attributes.getNumber("timeout").intValue());
        rbta.setReadOnly(attributes.getBoolean("readOnly"));
        rbta.setQualifier(attributes.getString("value"));
        ArrayList rollBackRules = new ArrayList();
        Class>[] rbf = attributes.getClassArray("rollbackFor");
        Class[] var7 = rbf;
        int var8 = rbf.length;
}
第二のステップは、Oopエージェントと同じTransationInterceptrであり、TransationInterceptorはMethodInterceptorから継承されています.
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
    public TransactionInterceptor() {
    }

    public TransactionInterceptor(PlatformTransactionManager ptm, Properties attributes) {
        this.setTransactionManager(ptm);
        this.setTransactionAttributes(attributes);
    }

    public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) {
        this.setTransactionManager(ptm);
        this.setTransactionAttributeSource(tas);
    }
    //         
    public Object invoke(final MethodInvocation invocation) throws Throwable {
        Class> targetClass = invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null;
        //     invokeWithinTransaction  
        return this.invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
            public Object proceedWithInvocation() throws Throwable {
                return invocation.proceed();
            }
        });
    }

}
上記のソースコードを通じて、最終的にはプロキシのコールバック方法でinvoke WithinTransactionを実行することが分かりました.これはまず容器から事務管理器Platform Transation Managerを獲得します.事務管理器はまず事務を作成します.実行文が異常が発生したら、事務管理器を通じてロールバックします.正常に事務を提出してください.
protected Object invokeWithinTransaction(Method method, Class> targetClass, final TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
        final TransactionAttribute txAttr = this.getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
        //        transationManager
        final PlatformTransactionManager tm = this.determineTransactionManager(txAttr);
        final String joinpointIdentification = this.methodIdentification(method, targetClass, txAttr);
        if (txAttr != null && tm instanceof CallbackPreferringPlatformTransactionManager) {
            try {
                Object result = ((CallbackPreferringPlatformTransactionManager)tm).execute(txAttr, new TransactionCallback() {
                
            TransactionAspectSupport.TransactionInfo txInfo = this.createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
            Object retVal = null;

            try {
                //   sql  
                retVal = invocation.proceedWithInvocation();
            } catch (Throwable var15) {
                //          
                this.completeTransactionAfterThrowing(txInfo, var15);
                throw var15;
            } finally {
                this.cleanupTransactionInfo(txInfo);
            }
            //     
            this.commitTransactionAfterReturning(txInfo);
            return retVal;
        }
    }