码迷,mamicode.com
首页 > 编程语言 > 详细

spring事务

时间:2020-03-29 22:45:24      阅读:94      评论:0      收藏:0      [点我收藏+]

标签:tst   except   local   使用方法   factory   date   aspect   number   row   

使用
ioc初始化过程注册代理类生成器,加载相关advisor到容器中
getBean时通过BeanPostProcessor回调生成代理类
通过代理类调用方法的流程

top

使用

事务的四个特性

1、原子性
2、一致性
原子性和一致性紧密联系,区别是什么?
举例:A给B转100块钱,需要两步:
1、A = A-100
2、B = B+100
原子性指把这两步放入到一个事务中,要么都执行成功,要么都失败。
一致性指的是在写代码的时候,写了1,就一定要写2,否则数据出现不一致的情况。
3、持久性:事务一旦提交,会写入到持久化存储器中,就算系统崩溃了,数据也能找回。
4、隔离性:多个事务处理相同数据的时候,他们之间应该是独立的,不能互相影响。

核心接口/类

spring本身不管理事务的具体实现,通过提供模板接口,然后持久化平台通过扩展该接口来实现事务的管理。
技术图片

了解一下jdbc的事务和hibernate的事务。

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
   <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

持久化平台通过PlatformTrasactionManager的getTraction方法可以获取到事务,参数为TransactionDefination对象,TransactionDefination对象包含了事务的配置信息,这样持久化平台就知道了事务的配置信息,自己去实现事务的管理。

spring可配置事务的属性有哪些

传播行为
事务超时
回滚规则
隔离规则:定义了一个事务可以看到另一个事务中的哪些数据
是否只读

事务传播行为

spring支持7中事务传播行为,A方法调用B方法:
1、A有事务,B加入A事务,A无事务,B无事务运行
2、A有事务,B加入,A无事务,B开启新事务
3、A有事务,A事务挂起,B开启自己事务:两个事务互相独立
4、A有事务,B开启新事务,嵌套到A中:B事务失败不会影响A,A事务失败会把B也回滚。
5、A有事务,B加入,A无事务,B抛出异常
6、A有事务,挂起,B无事务运行
7、A有事务,抛异常

事务不生效的几种可能

1、数据库引擎不支持事务。
innodb支持事务,myisam不支持事务

2、事务所在的类必须被spring容器所管理

3、@Transaction注解的方法必须为public

4、自身调用
spring事务传播是指两个方法是在不同的类中,如果两个方法属于同一个类,那么事务的传播配置就会失效。

@Service
public class OrderServiceImpl implements OrderService {

    @Transactional
    public void update(Order order) {
        this.updateOrder(order);
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateOrder(Order order) {
        // update order
    }

}

上面代码,updateOrder方法的事务配置是不会生效的,
原因:spring声明事务是通过spring aop实现的,spring aop会生成一个代理类,在代理类中执行事务管理逻辑,上面代码中update方法调用this.updateOrder方法不是通过代理类,所以updateOrder方法事务没有生效。
那么如何解决?
可以通过aop代理类调用updateOrder方法。

1、开启
<aop:aspectj-autoproxy expose-proxy="true"/>
2、this.updateOrder();-----------修改为--------->AopContext.currentProxy()).updateOrder();

5、异常没有正确抛出

public class OrderServiceImpl implements OrderService {

    @Transactional
    public void updateOrder(Order order) {
        try {
            // update order
        } catch {
//这里没有抛出异常
        }
    }

}
public class OrderServiceImpl implements OrderService {

    @Transactional
    public void updateOrder(Order order) {
        try {
            // update order
        } catch {//这里必须改成运行时异常
            throw new Exception("更新错误");
        } 
    }

}

隔离级别

数据库中隔离级别相关参考:https://github.com/sunyanhui123/note/issues/4#issue-399319103
spring的隔离级别有5中:
1、采用数据库设置的隔离级别
2、对应数据库的uncommited
3、commited
4、repeatable
5、串行

只读

当一个事务中有多条查询语句的时候,开启只读属性,则数据库会自动进行sql优化

回滚

默认情况下,遇到运行时异常事务会回滚,这里可以指定异常类型,还可以指定哪些异常不回滚

编程式事务

声明式事务是spring通过注解实现,提前定义好的一些。编程式事务则是在代码中自己进行事务管理,缺点是代码侵入,优点是可以自己管理事务。

声明式事务使用

推荐使用存注解方式
首先xml中配置

<tx:annotation-driven transaction-manager="transactionManager"/>

    <bean id="sessionFactory" 
            class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
        <property name="configLocation" value="classpath:hibernate.cfg.xml" /> 
        <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
    </bean> 

    <!-- 定义事务管理器(声明式的事务) --> 
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

然后在相关方法中加入注解即可

返回顶部

ioc初始化过程注册代理类生成器,加载相关advisor到容器中

1、spring容器在初始化过程中,遇到spring开启事务的标签tx:annotation-driven,会通过命名空间找到命名空间处理器TxNamespaceHandler,该处理器的初始化方法中给spring事务的根标签绑定了一个标签解析器AnnotationDrivenBeanDefinitionParser。
然后调用解析器的parse方法对事务标签进行解析:
2、首先注册一个代理类生成器到容器,这个生成器封装了生成代理类的方法
3、创建三种类型的bean,beanClass分别为AnnotationTransactionAttributeSource、TransactionInterceptor、BeanFactoryTransactionAttributeSourceAdvisor,他们分别封装了相应的pointcut、advice、advisor,同时将前两个bean封装到第三个bean里。
然后将这三种类型的bean都加入到spring容器中。

TxNamespaceHandler解析器的init方法:给spring事务标签绑定了标签解析器。

@Override
public void init() {
    registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
    registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
    registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
}

AnnotationDrivenBeanDefinitionParser.parse:在spring ioc初始化过程中,遇到自定义标签tx:annotation-driven,执行该方法解析事务相关标签

@Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        registerTransactionalEventListenerFactory(parserContext);
        String mode = element.getAttribute("mode");
        /***
         * 对于mode属性的判断
         * 如果我们需要使用AspectJ的方式进行事务切入(Spring中的事务是以AOP为基础的),那么可以使用这样的配置:
         * <tx:annotation-driven transaction-manager="transactionManager" mode="aspectj"/>
         */
        if ("aspectj".equals(mode)) {
            // mode="aspectj"
            registerTransactionAspect(element, parserContext);
        }
        else {//正常情况进入这个分支
            // mode="proxy"
            AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
        }
        return null;
    }

AnnotationDrivenBeanDefinitionParser.configureAutoProxyCreator:
该方法首先注册了代理类生成器。
然后创建三种类型的bean,beanClass分别为AnnotationTransactionAttributeSource、TransactionInterceptor、BeanFactoryTransactionAttributeSourceAdvisor,他们分别封装了相应的pointcut、advice、advisor,同时将前两个bean封装到第三个bean里。
后续获取advisor就是获取这三个bean。

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
        //注册代理类生成器
        AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

        String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
        if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
            Object eleSource = parserContext.extractSource(element);

            // 创建AnnotationTransactionAttributeSource类型的Bean,该类型bean代表pointcut
            RootBeanDefinition sourceDef = new RootBeanDefinition(
                    "org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
            sourceDef.setSource(eleSource);
            sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

            // 创建TransactionInterceptor类型的Bean,该类型bean代表advice
            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);

            // 创建BeanFactoryTransactionAttributeSourceAdvisor实例bean
            RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
            advisorDef.setSource(eleSource);
            advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            //将上面创建的AnnotationTransactionAttributeSource和TransactionInterceptor封装到BeanFactoryTransactionAttributeSourceAdvisor中
         //将advice和pointcut封装到advisor中
            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);
            //将上面三个Bean注册进IOC中
            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);
        }
    }

返回顶部

getBean时通过BeanPostProcessor回调生成代理类

本章是在getBean时,通过BeanPostProcessor回调创建代理类的过程。

首先要判断是否需要创建代理类,如何判断?
该bean是否能找到匹配的advisor,如果能找到,就创建代理类。
其实就是寻找事务相关注解,匹配注解,解析注解的过程。

上面流程会将需要事务增强的方法都封装到advisor中,接下来是getBean的时候,根据BeanPostProcessor回调机制调用,根据要创建的bean去advisor中去匹配,如果匹配成功,则创建代理类。

AbstractAutoProxyCreator.postProcessAfterInitialization:

@Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        //几种不需要代理的情况,直接返回
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // 这里是主要验证的地方,传入Bean的class与beanName去判断此Bean有哪些Advisor
       //获取匹配的advisor,然后转换成拦截器链条(放入一个list中)
//入口
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        // 如果有相应的advisor被找到,则用advisor与此bean做一个动态代理,将这两个的信息
        // 放入代理类中进行代理
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            // 创建代理的地方
            Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            // 返回代理对象
            return proxy;
        }
        // 如果此Bean没有一个Advisor匹配,将返回null也就是DO_NOT_PROXY
        // 也就是会走到这一步,将其cacheKey,false存入Map中
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        // 不代理直接返回原bean
        return bean;
    }

AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean:获取advisor链。

@Override
    protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
        List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
        if (advisors.isEmpty()) {
            return DO_NOT_PROXY;
        }
        return advisors.toArray();
    }

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        //获取所有候选advisor
        List<Advisor> candidateAdvisors = findCandidateAdvisors();//入口1
        //获取可用advisor
        //入口2
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

AbstractAdvisorAutoProxyCreator.findCandidateAdvisors:获取所有advisor

protected List<Advisor> findCandidateAdvisors() {
        return this.advisorRetrievalHelper.findAdvisorBeans();
    }

##BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans:将容器初始化阶段装进去的advisor取出来
public List<Advisor> findAdvisorBeans() {
        String[] advisorNames = this.cachedAdvisorBeanNames;
        if (advisorNames == null) {
            advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                    this.beanFactory, Advisor.class, true, false);
            this.cachedAdvisorBeanNames = advisorNames;
        }
        if (advisorNames.length == 0) {
            return new ArrayList<Advisor>();
        }

        List<Advisor> advisors = new ArrayList<Advisor>();
        for (String name : advisorNames) {
            if (isEligibleBean(name)) {
                advisors.add(this.beanFactory.getBean(name, Advisor.class));
            }
        }
        return advisors;
    }

AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply:获取匹配advisor

    protected List<Advisor> findAdvisorsThatCanApply(
            List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

        ProxyCreationContext.setCurrentProxiedBeanName(beanName);
        try {
            return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
        }
        finally {
            ProxyCreationContext.setCurrentProxiedBeanName(null);
        }
    }
//    AopUtils.findAdvisorsThatCanApply:
    public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
        if (candidateAdvisors.isEmpty()) {
            return candidateAdvisors;
        }
        List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
        //IntroductionAdvisor为引介增强
        for (Advisor candidate : candidateAdvisors) {
            //暂不考虑引介增强,这里一个都不会进入
            if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
                eligibleAdvisors.add(candidate);
            }
        }
        boolean hasIntroductions = !eligibleAdvisors.isEmpty();
        for (Advisor candidate : candidateAdvisors) {
            if (candidate instanceof IntroductionAdvisor) {
                //暂不考虑引介增强,这里一个都不会进入
                continue;
            }
            if (canApply(candidate, clazz, hasIntroductions)) {//入口
                eligibleAdvisors.add(candidate);
            }
        }
        return eligibleAdvisors;
    }

public static boolean canApply(Advisor advisor, Class<?> targetClass) {
        return canApply(advisor, targetClass, false);
    }
    public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
        //暂不考虑引介增强,这里一个都不会进入
        if (advisor instanceof IntroductionAdvisor) {
            return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
        }
        else if (advisor instanceof PointcutAdvisor) {//切点
            PointcutAdvisor pca = (PointcutAdvisor) advisor;
            return canApply(pca.getPointcut(), targetClass, hasIntroductions);//入口
        }
        else {//通知类型的advisor,不需要匹配,直接返回
            // It doesn‘t have a pointcut so we assume it applies.
            return true;
        }
    }

1、上面的方法中提到引介增强的概念,在此做简要说明,引介增强是一种比较特殊的增强类型,它不是在目标方法周围织入增强,而是为目标类创建新的方法和属性,所以引介增强的连接点是类级别的,而非方法级别的。通过引介增强,我们可以为目标类添加一个接口的实现,即原来目标类未实现某个接口,通过引介增强可以为目标类创建实现该接口的代理。另外这个方法用两个重载的canApply方法为目标类寻找匹配的增强器,其中第一个canApply方法会调用第二个canApply方法并将第三个参数传为false。
2、回顾一下容器初始化阶段注入到beanFactory中的三个bean:
AnnotationTransactionAttributeSource、TransactionInterceptor、BeanFactoryTransactionAttributeSourceAdvisor,
其中BeanFactoryTransactionAttributeSourceAdvisor包含另外两个。
这个BeanFactoryTransactionAttributeSourceAdvisor就是我们现在真正处理的advisor。
所以接下来进入的方法的第一个参数就是BeanFactoryTransactionAttributeSourceAdvisor的内部属性TransactionAttributeSourcePointcut。

 return canApply(pca.getPointcut(), targetClass, hasIntroductions);//入口
 public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
        private TransactionAttributeSource transactionAttributeSource;
        private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
            protected TransactionAttributeSource getTransactionAttributeSource() {
                return org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor.this.transactionAttributeSource;
            }
        };
    }

继续接上面代码:

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
        Assert.notNull(pc, "Pointcut must not be null");
        if (!pc.getClassFilter().matches(targetClass)) {
            return false;
        }

        //此时的pc表示TransactionAttributeSourcePointcut
        //pc.getMethodMatcher()返回的正是自身(this)
        MethodMatcher methodMatcher = pc.getMethodMatcher();
        if (methodMatcher == MethodMatcher.TRUE) {
            return true;
        }

        IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
        if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
            introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
        }
        //对于事物的配置不仅仅局限于在函数上配置,我们都知道,在类或接口上的配置可以延续到类中的每个函数
        //获取对应类的所有接口
        Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
        classes.add(targetClass);
        //对类进行遍历
        for (Class<?> clazz : classes) {
            //反射获取类中所有的方法
            Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
            for (Method method : methods) {
                //对类和方法进行增强器匹配
                if ((introductionAwareMethodMatcher != null &&
                        introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
                        methodMatcher.matches(method, targetClass)) {//入口  这个匹配就是找@Transaction注解的过程
                    return true;
                }
            }
        }
        return false;
    }
//    TransactionAttributeSourcePointcut.matches
    public boolean matches(Method method, Class<?> targetClass) {
        if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
            return false;
        } else {
            TransactionAttributeSource tas = this.getTransactionAttributeSource();
            return tas == null || tas.getTransactionAttribute(method, targetClass) != null;
        }
    }

AbstractFallbackTransactionAttributeSource.getTransactionAttribute:做了一层缓存

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

        // First, see if we have a cached value.
        Object cacheKey = getCacheKey(method, targetClass);
        TransactionAttribute 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 cached;
            }
        }
        else {
            // We need to work it out.
            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;
        }
    }
    @Nullable
    protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
        if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
            return null;
        }

        /**
         * 如果方法中存在事务属性,则使用方法上的属性,否则使用方法所在的类上的属性,
         * 如果方法所在类的属性上还是没有搜寻到对应的事务属性,那么在搜寻接口中的方法,
         * 再没有的话,最后尝试搜寻接口的类上面的声明
         */

        // method代表接口中的方法,specificMethod代表实现类中的方法
        Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

        // 查看方法中是否存在事务声明
        TransactionAttribute txAttr = findTransactionAttribute(specificMethod);//入口
        if (txAttr != null) {
            return txAttr;
        }

        // 查看方法所在类中是否存在事务声明
        txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());//入口
        if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
            return txAttr;
        }

        // 如果存在接口,则到接口中去寻找
        if (specificMethod != method) {
            // 查找接口方法
            txAttr = findTransactionAttribute(method);
            if (txAttr != null) {
                return txAttr;
            }
            // 到接口中的类中去寻找
            txAttr = findTransactionAttribute(method.getDeclaringClass());
            if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
                return txAttr;
            }
        }

        return null;
    }

AnnotationTransactionAttributeSource.findTransactionAttribute:

@Override
    protected TransactionAttribute findTransactionAttribute(Method method) {
        return determineTransactionAttribute(method);
    }
    protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
        if (element.getAnnotations().length > 0) {
            for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
                TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);
                if (attr != null) {
                    return attr;
                }
            }
        }
        return null;
    }
    @Override
    @Nullable
    public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {
        AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
                ae, Transactional.class, false, false);
        if (attributes != null) {
            return parseTransactionAnnotation(attributes);
        }
        else {
            return null;
        }
    }
    protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
        /***
         * 首先会判断当前的类是否含有 Transactional注解,这是事务属性的基础,
         * 当然如果有的话会继续调用parseTransactionAnnotation 方法解析详细的属性。
         */
        RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
        Propagation propagation = attributes.getEnum("propagation");
        // 解析propagation
        rbta.setPropagationBehavior(propagation.value());
        Isolation isolation = attributes.getEnum("isolation");
        // 解析isolation
        rbta.setIsolationLevel(isolation.value());
        // 解析timeout
        rbta.setTimeout(attributes.getNumber("timeout").intValue());
        // 解析readOnly
        rbta.setReadOnly(attributes.getBoolean("readOnly"));
        // 解析value
        rbta.setQualifier(attributes.getString("value"));
        ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<>();
        // 解析rollbackFor
        Class<?>[] rbf = attributes.getClassArray("rollbackFor");
        for (Class<?> rbRule : rbf) {
            RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
            rollBackRules.add(rule);
        }
        // 解析rollbackForClassName
        String[] rbfc = attributes.getStringArray("rollbackForClassName");
        for (String rbRule : rbfc) {
            RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
            rollBackRules.add(rule);
        }
        // 解析noRollbackFor
        Class<?>[] nrbf = attributes.getClassArray("noRollbackFor");
        for (Class<?> rbRule : nrbf) {
            NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
            rollBackRules.add(rule);
        }
        // 解析noRollbackForClassName
        String[] nrbfc = attributes.getStringArray("noRollbackForClassName");
        for (String rbRule : nrbfc) {
            NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
            rollBackRules.add(rule);
        }
        rbta.getRollbackRules().addAll(rollBackRules);
        return rbta;
    }

返回顶部

通过代理类调用方法的流程

最终执行的是链条中每个advice的invoke方法。回顾前面spring容器初始化过程声明的三个bean,其中TransactionInterceptor就是代表advice的。所以最终执行的是它的invoke方法。

//    TransactionInterceptor
    @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 TransactionAspectSupport.InvocationCallback() {
            @Override
            public Object proceedWithInvocation() throws Throwable {
                return invocation.proceed();
            }
        });
    }

返回顶部

spring事务

标签:tst   except   local   使用方法   factory   date   aspect   number   row   

原文地址:https://www.cnblogs.com/yanhui007/p/12595553.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!