(三)Spring源码分析----tx事务管理

Spring事务是基于AOP代理完成的,有了前面的AOP源码分析基础,Spring事务理解起来就比较简单了,我们先看一看Spring中的注解版事务配置例子:

Spring配置类:同开启AOP功能一样,事务功能也需要通过注解@EnableTransactionManagement进行开启,同时需要配置事务管理器,默认使用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最终发现是c3p0包中的ComboPooledDataSource数据源的原因,默认ComboPooledDataSource数据源在开启事务前不会关闭数据库连接的自动提交所以导致事务不会回滚,需要继承AbstractConnectionCustomizer类来将数据库连接自动提交关闭掉。

public class YourConnectionCustomizer extends AbstractConnectionCustomizer {

    @Override
    public void onCheckOut(Connection c, String parentDataSourceIdentityToken) throws Exception {
        super.onCheckOut(c, parentDataSourceIdentityToken);
        c.setAutoCommit(false);
    }
}

言归正传,我们一起来探究Spring事务的原理,开启事务通过@EnableTranscationManagement点击进去查看会发现和AOP是一个套路:都是通过Import来引入Spring组件完成期待功能

// 引入TransactionManagementConfigurationSelector组件
@Import({TransactionManagementConfigurationSelector.class})
public @interface EnableTransactionManagement {
    boolean proxyTargetClass() default false;

    AdviceMode mode() default AdviceMode.PROXY;

    int order() default 2147483647;
}

查看TransactionManagementConfigurationSelector组件完成了哪些功能,通过源码发现Selector又为我们注册了两个新的组件AutoProxyRegistrar和ProxyTranctionManagementConfiguration,我们来逐一分析这两个组件的作用:

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;
    }

}

             ProxyTranctionManagementConfiguration:它的作用主要是向容器中创建事务增强器advisor,第一步在增强器中添加事务属性资源transationAttributeSource,第二步为增强器中添加事务拦截器

@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;
    }

}

第一步添加的事务属性资源解析器transationAdvisor(), transationAdvisor用于注册一个注解事务解析器AnnotationTransationAttributeSource()用于解析事务注解信息

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;
}

第二步为事务增强器添加一个方法拦截器TransationInterceptor,同aop代理一样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();
            }
        });
    }

}

通过上面源码我们可知事务最终是调用代理类的回调方法执行invokeWithinTransaction(),它首先会从容器中获得事务管理器PlatformTransactionManager,事务管理器首先创建事务,执行语句如果出现异常通过事务管理器回滚,如果正常提交事务。

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;
        }
    }

 

你可能感兴趣的:(java基础)