美文网首页
【Spring源码】声明式事务源码分析

【Spring源码】声明式事务源码分析

作者: RalapHao | 来源:发表于2019-04-12 14:46 被阅读0次

环境搭建

  1. 加入相关依赖
    c3p0、spring-jdbc、mysql-connector-java、spring-context
    注意:spring-jdbc和spring-context 的版本尽量保持一致(不一致可能引起jar包冲突,报错信息 org.springframework.util.ClassUtils.getQualifiedMethodName(Ljava/lang/reflect/Method;Ljava/lang/Clas)
  2. 配置数据源DataSource
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setUser("xxx");
    dataSource.setPassword("xxx");
    dataSource.setDriverClass("com.mysql.jdbc.Driver");
    dataSource.setJdbcUrl("jdbc:mysql://xxxx:3306/test?useUnicode=true&characterEncoding=utf8");
  3. 配置JdbcTemplate
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());//可以直接调用方法获取数据源,这里和容器中的DataSource一致(Spring的机制)
  4. 配置事务管理器TransactionManager
    DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource());
  5. 开启事务
    @EnableTransactionManagement

原理

  1. @EnableTransactionManagement
    开启事务,注入TransactionManagementConfigurationSelector组件
  2. TransactionManagementConfigurationSelector
 protected String[] selectImports(AdviceMode adviceMode) {
        //adviceMode默认为AdviceMode mode() default AdviceMode.PROXY
        //所以重点关注AutoProxyRegistrar、ProxyTransactionManagementConfiguration
        switch(adviceMode) {
        case PROXY:
            return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
        case ASPECTJ:
            return new String[]{"org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration"};
        default:
            return null;
        }
    }

AutoProxyRegistrar相关
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean candidateFound = false;
        Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
        for (String annoType : annoTypes) {
            AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
            Object mode = candidate.get("mode");
            Object proxyTargetClass = candidate.get("proxyTargetClass");
            if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
                    Boolean.class == proxyTargetClass.getClass()) {
                candidateFound = true;
                if (mode == AdviceMode.PROXY) {
                                        //注册自动代理创建器
                    AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                    if ((Boolean) proxyTargetClass) {
                        AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                        return;
                    }
                }
            }
        }
...
    }

//这里和AOP模式相,AOP为容器注入AnnotationAwareAspectJAutoProxyCreator,
//事务这里注入的是InfrastructureAdvisorAutoProxyCreator(后置处理器)
//InfrastructureAdvisorAutoProxyCreator主要是在使用后置处理器在对象创建后,结合增强器包装对象,在代对象执行方法通过拦截器链进行调用
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;
    }

ProxyTransactionManagementConfiguration(为事务注入增强器)

//注入事务增强器
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionAttributeSource(transactionAttributeSource());
        advisor.setAdvice(transactionInterceptor());
        advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
        return advisor;
    }

        //注入事务属相相关属性配置(SpringTransactionAnnotationParser、JtaTransactionAnnotationParser、Ejb3TransactionAnnotationParser)
    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource();
    }
        //事务拦截器(MethodInterceptor)
    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionInterceptor transactionInterceptor() {
        TransactionInterceptor interceptor = new TransactionInterceptor();
                //设置事务属性信息
        interceptor.setTransactionAttributeSource(transactionAttributeSource());
        if (this.txManager != null) {
                        //设置事务管理信息
            interceptor.setTransactionManager(this.txManager);
        }
        return interceptor;
    }

      
    @Override
    public Object invoke(final MethodInvocation invocation) throws Throwable {
        // Work out the target class: may be {@code null}.
        // The TransactionAttributeSource should be passed the target class
        // as well as the method, which may be from an interface.
        Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

        // Adapt to TransactionAspectSupport's invokeWithinTransaction...
        return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
            @Override
            public Object proceedWithInvocation() throws Throwable {
                return invocation.proceed();
            }
        });
    }
    
//目标方法执行前,执行拦截器链
    protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
            throws Throwable {
                //获取属性信息
        // If the transaction attribute is null, the method is non-transactional.
        final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
                //获取管理信息
        final PlatformTransactionManager tm = determineTransactionManager(txAttr);
               //获取目标方法
        final String joinpointIdentification = methodIdentification(method, targetClass);

        if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
            // Standard transaction demarcation with getTransaction and commit/rollback calls.
            TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
            Object retVal = null;
            try {
                                //执行方法链(包括目标方法)
                // This is an around advice: Invoke the next interceptor in the chain.
                // This will normally result in a target object being invoked.
                retVal = invocation.proceedWithInvocation();
            }
            catch (Throwable ex) {
                                //异常回滚
                // target invocation exception
                completeTransactionAfterThrowing(txInfo, ex);
                throw ex;
            }
            finally {
                cleanupTransactionInfo(txInfo);
            }
                        //提交事务
            commitTransactionAfterReturning(txInfo);
            return retVal;
        }

        else {
            // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
            try {
                Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
                        new TransactionCallback<Object>() {
                            @Override
                            public Object doInTransaction(TransactionStatus status) {
                                TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
                                try {
                                    return invocation.proceedWithInvocation();
                                }
                                catch (Throwable ex) {
                                    if (txAttr.rollbackOn(ex)) {
                                        // A RuntimeException: will lead to a rollback.
                                        if (ex instanceof RuntimeException) {
                                            throw (RuntimeException) ex;
                                        }
                                        else {
                                            throw new ThrowableHolderException(ex);
                                        }
                                    }
                                    else {
                                        // A normal return value: will lead to a commit.
                                        return new ThrowableHolder(ex);
                                    }
                                }
                                finally {
                                    cleanupTransactionInfo(txInfo);
                                }
                            }
                        });

                // Check result: It might indicate a Throwable to rethrow.
                if (result instanceof ThrowableHolder) {
                    throw ((ThrowableHolder) result).getThrowable();
                }
                else {
                    return result;
                }
            }
            catch (ThrowableHolderException ex) {
                throw ex.getCause();
            }
        }
    }
        //获取事务管理信息
    protected PlatformTransactionManager determineTransactionManager(TransactionAttribute txAttr) {
        // Do not attempt to lookup tx manager if no tx attributes are set
        if (txAttr == null || this.beanFactory == null) {
                        //事务信息不存存在,返回默认事务管理器
            return getTransactionManager();
        }
                //是否标记@Qualifier
        String qualifier = txAttr.getQualifier();
        if (StringUtils.hasText(qualifier)) {
                        //指定@Qualifier
            return determineQualifiedTransactionManager(qualifier);
        }
        else if (StringUtils.hasText(this.transactionManagerBeanName)) {
                        //根据指定的transactionManagerBeanName进行设置
            return determineQualifiedTransactionManager(this.transactionManagerBeanName);
        }
        else {
                         //默认配置
            PlatformTransactionManager defaultTransactionManager = getTransactionManager();
            if (defaultTransactionManager == null) {
                defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class);
                this.transactionManagerCache.putIfAbsent(
                        DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
            }
            return defaultTransactionManager;
        }
    }

总结

声明式事务主要用到的模式是AOP,通过后置处理器将对象代理,通过ProxyTransactionManagementConfiguration喂食物注入增强器、拦截器,最后通过拦截器封装TransationInfo信息(包括事务信息、事务管理器信息),最后执行拦截器链(包含目标方法),通过异常判事务的回滚与提交

相关文章

网友评论

      本文标题:【Spring源码】声明式事务源码分析

      本文链接:https://www.haomeiwen.com/subject/cbwqwqtx.html