Spring事务管理(四)-@Transactional和声明式事务

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

在前几篇中,介绍了Spring事务中核心的原理,如事务AOP代理TransactionProxyFactoryBean及事务管理器PlatformmTransactionManager,而最终以@Transactional注解这种非侵入式甚至近乎无感知的方式运行在我们的大大小小的项目中,只需要在配置文件中加上简单的配置,因此也就称为声明式事务:事务与业务解耦。

在spring配置文件中加上事务注解驱动,以及事务管理器






    

此时,在需要事务的方法上加上@Transactional即可(前提是类被spring容器管理)。要分析其运行的原理,得从事务注解驱动的配置开始。根据Spring解析xml Namespace的规则,直接查找TxNamespaceHandler,对annotation-driven的解析由AnnotationDrivenBeanDefinitionParser执行。

public BeanDefinition parse(Element element, ParserContext parserContext) {
    registerTransactionalEventListenerFactory(parserContext);
    String mode = element.getAttribute("mode");
    if ("aspectj".equals(mode)) {
        // mode="aspectj"
        registerTransactionAspect(element, parserContext);
    }
    else {
        // mode="proxy"
        AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
    }
    return null;
}

默认情况下,不用配置mode,即由其内部静态类AopAutoProxyConfigurer完成配置

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
	// 配置AOP自动代理
    AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
	// 事务切面名称为org.springframework.transaction.config.internalTransactionAdvisor
    String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
    if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
        Object eleSource = parserContext.extractSource(element);

        // Create the TransactionAttributeSource definition.
        // 定义事务属性源为AnnotationTransactionAttributeSource
        RootBeanDefinition sourceDef = new RootBeanDefinition(
                "org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
        sourceDef.setSource(eleSource);
        sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

        // Create the TransactionInterceptor definition.
        // 定义事务拦截器
        RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
        interceptorDef.setSource(eleSource);
        interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        registerTransactionManager(element, interceptorDef);
        interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
        String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

        // Create the TransactionAttributeSourceAdvisor definition.
        // 定义事务切面为BeanFactoryTransactionAttributeSourceAdvisor
        RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
        advisorDef.setSource(eleSource);
        advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
        advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
        if (element.hasAttribute("order")) {
            advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
        }
        parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);

        CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
        compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
        compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
        compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
        parserContext.registerComponent(compositeDef);
    }
}

主要配置的有三部分:

  1. 事务属性源TransactionAttributeSource
  2. 事务拦截器TransactionInterceptor
  3. 事务切面TransactionAttributeSourceAdvisor

事务属性源

这里配置的事务属性源是AnnotationTransactionAttributeSource,支持根据类和方法获取事务属性。

@Override
@Nullable
protected TransactionAttribute findTransactionAttribute(Method method) {
    return determineTransactionAttribute(method);
}

@Override
@Nullable
protected TransactionAttribute findTransactionAttribute(Class clazz) {
    return determineTransactionAttribute(clazz);
}

统一调用determineTransactionAttribute方法

protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {
	// 注解解析器解析事务注解
    for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
        TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);
        if (attr != null) {
            return attr;
        }
    }
    return null;
}

在AnnotationTransactionAttributeSource的构造方法中,初始化了注解解析器

public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
    this.publicMethodsOnly = publicMethodsOnly;
    this.annotationParsers = new LinkedHashSet<>(2);
    // 支持Spring的@Transactional
    this.annotationParsers.add(new SpringTransactionAnnotationParser());
    // 支持javax.transaction.Transactional
    if (jta12Present) {
        this.annotationParsers.add(new JtaTransactionAnnotationParser());
    }
    // 支持javax.ejb.TransactionAttribute
    if (ejb3Present) {
        this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
    }
}

SpringTransactionAnnotationParser中判断类和方法上是否有@Transactional,然后解析注解的属性

public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {
	// 判断类和方法上的@Transactional
    AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
            ae, Transactional.class, false, false);
    if (attributes != null) {
    	// 解析@Transactional
        return parseTransactionAnnotation(attributes);
    }
    else {
        return null;
    }
}

创建事务属性对象RuleBasedTransactionAttribute,获取事务属性配置

protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
    RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
    Propagation propagation = attributes.getEnum("propagation");
    rbta.setPropagationBehavior(propagation.value());
    Isolation isolation = attributes.getEnum("isolation");
    rbta.setIsolationLevel(isolation.value());
    rbta.setTimeout(attributes.getNumber("timeout").intValue());
    rbta.setReadOnly(attributes.getBoolean("readOnly"));
    // value指定哪个事务管理器
    rbta.setQualifier(attributes.getString("value"));
    ArrayList rollBackRules = new ArrayList<>();
    Class[] rbf = attributes.getClassArray("rollbackFor");
    for (Class rbRule : rbf) {
        RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
        rollBackRules.add(rule);
    }
    String[] rbfc = attributes.getStringArray("rollbackForClassName");
    for (String rbRule : rbfc) {
        RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
        rollBackRules.add(rule);
    }
    Class[] nrbf = attributes.getClassArray("noRollbackFor");
    for (Class rbRule : nrbf) {
        NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
        rollBackRules.add(rule);
    }
    String[] nrbfc = attributes.getStringArray("noRollbackForClassName");
    for (String rbRule : nrbfc) {
        NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
        rollBackRules.add(rule);
    }
    rbta.getRollbackRules().addAll(rollBackRules);
    return rbta;
}

@Transactional的value值定义的是由哪个事务管理器管理,如果没有配置rollbackFor和noRollbackFor属性,由RuleBasedTransactionAttribute的父类DefaultTransactionAttribute默认定义异常回滚规则:遇到运行时异常和Error回滚事务。

public boolean rollbackOn(Throwable ex) {
    return (ex instanceof RuntimeException || ex instanceof Error);
}

至此,事务属性的解析很清晰了,那么又是在何处调用事务属性源的findTransactionAttribute方法?

事务切面

BeanFactoryTransactionAttributeSourceAdvisor继承自AbstractBeanFactoryPointcutAdvisor,重要的是定义了切点为TransactionAttributeSourcePointcut。

public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

    @Nullable
    private TransactionAttributeSource transactionAttributeSource;

    private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
        @Override
        @Nullable
        protected TransactionAttributeSource getTransactionAttributeSource() {
            return transactionAttributeSource;
        }
    };
}

切点需要的事务属性源即上面创建的AnnotationTransactionAttributeSource。匹配是否事务管理由TransactionAttributeSourcePointcut中的matches方法决定。

@Override
public boolean matches(Method method, @Nullable Class targetClass) {
    if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
        return false;
    }
    TransactionAttributeSource tas = getTransactionAttributeSource();
    // 判断是否事务管理
    return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

getTransactionAttribute方法执行的是AnnotationTransactionAttributeSource父类AbstractFallbackTransactionAttributeSource中的方法

public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class targetClass) {
    if (method.getDeclaringClass() == Object.class) {
        return null;
    }

    // First, see if we have a cached value.
    Object cacheKey = getCacheKey(method, targetClass);
    Object cached = this.attributeCache.get(cacheKey);
    if (cached != null) {
        // Value will either be canonical value indicating there is no transaction attribute,
        // or an actual transaction attribute.
        if (cached == NULL_TRANSACTION_ATTRIBUTE) {
            return null;
        }
        else {
            return (TransactionAttribute) cached;
        }
    }
    else {
        // We need to work it out.
        // 没有缓存,根据方法和Class对象计算事务属性
        TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
        // Put it in the cache.
        if (txAttr == null) {
            this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
        }
        else {
            String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
            if (txAttr instanceof DefaultTransactionAttribute) {
                ((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
            }
            this.attributeCache.put(cacheKey, txAttr);
        }
        return txAttr;
    }
}

这里增加了一层缓存,第一次调用时执行computeTransactionAttribute方法

protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class targetClass) {
    // Don't allow no-public methods as required.
    // 只允许public方法
    if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
        return null;
    }

    // Ignore CGLIB subclasses - introspect the actual user class.
    // 忽略CGLIB生成的对象,找到实际用户使用的Class
    Class userClass = (targetClass != null ? ClassUtils.getUserClass(targetClass) : null);
    // The method may be on an interface, but we need attributes from the target class.
    // If the target class is null, the method will be unchanged.
    // 从接口方法找到实际的实现类方法
    Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);
    // If we are dealing with method with generic parameters, find the original method.
    // 如果方法上存在泛型,转换获取真正的方法
    specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);

    // First try is the method in the target class.
    // 从方法上获取事务对象
    TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
    if (txAttr != null) {
        return txAttr;
    }

    // Second try is the transaction attribute on the target class.
    // 方法不存在的话,从类上获取事务对象
    txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
    if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
        return txAttr;
    }

    if (specificMethod != method) {
        // Fallback is to look at the original method.
        txAttr = findTransactionAttribute(method);
        if (txAttr != null) {
            return txAttr;
        }
        // Last fallback is the class of the original method.
        txAttr = findTransactionAttribute(method.getDeclaringClass());
        if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
            return txAttr;
        }
    }

    return null;
}

@Transactional的优先级是:方法注解 > 类注解,这里的findTransactionAttribute执行的类就是AnnotationTransactionAttributeSource。

切面类配置完成后,需要绑定到Bean的生命周期中,这样在Bean创建时执行AOP代理,因此我们需要自动代理配置(关于自动代理,请见Spring源码-AOP(六)-自动代理与DefaultAdvisorAutoProxyCreator)。

基础自动代理

在tx:annotation-driven解析的开始,就注册了AOP的自动代理。

AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

由AopConfigUtils统一配置

public static void registerAutoProxyCreatorIfNecessary(
        ParserContext parserContext, Element sourceElement) {

	// 注册自动代理BeanDefinition
    BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
            parserContext.getRegistry(), parserContext.extractSource(sourceElement));
    // aop属性配置
    useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
    registerComponentIfNecessary(beanDefinition, parserContext);
}

自动代理BeanDefinition配置为InfrastructureAdvisorAutoProxyCreator,只对Advisor的role为ROLE_INFRASTRUCTURE代理

public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
        @Nullable Object source) {

    return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}

InfrastructureAdvisorAutoProxyCreator继承AbstractAdvisorAutoProxyCreator,重写isEligibleAdvisorBean方法,判断适合的Advisor。

protected boolean isEligibleAdvisorBean(String beanName) {
    return (this.beanFactory != null && this.beanFactory.containsBeanDefinition(beanName) &&
            this.beanFactory.getBeanDefinition(beanName).getRole() == BeanDefinition.ROLE_INFRASTRUCTURE);
}

自动代理的核心基类AbstractAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor接口,在Bean初始化完成后,查找所有Advisor,并过滤切点包含自己的Advisor,详细时间见Spring源码-AOP(六)-自动代理与DefaultAdvisorAutoProxyCreator)。

对于事务拦截器TransactionInterceptor的实现过程已经在Spring事务管理(二)-TransactionProxyFactoryBean原理说明了,这里就不赘述了。

转载于:https://my.oschina.net/u/2377110/blog/1617722

你可能感兴趣的:(java,python)