Spring事务源码分析总结

Spring事务是我们日常工作中经常使用的一项技术,Spring提供了编程、注解、aop切面三种方式供我们使用Spring事务,其中编程式事务因为对代码入侵较大所以不被推荐使用,注解和aop切面的方式可以基于需求自行选择,我们以注解的方式为例来分析Spring事务的原理和源码实现。

//配置事务管理器<tx:annotation-driven transaction-manager="transactionManager"/> <bean id="transactionManager"          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">     <property name="dataSource" ref="dataSource"/> </bean>

注意:在需要开启事务的方法上加上@Transactional注解即可,这里需要注意的是,当tx:annotation-driven/标签在不指定transaction-manager属性的时候,会默认寻找id固定名为transactionManager的bean作为事务管理器,如果没有id为transactionManager的bean并且在使用@Transactional注解时也没有指定value(事务管理器),程序就会报错

TxNamespaceHandler

@Overridepublic void init() {    //对tx:advice标签进行解析        registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());    //对annotation-driven标签进行解析      registerBeanDefinitionParser("annotation-driven", new         AnnotationDrivenBeanDefinitionParser());        registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());    }

AnnotationDrivenBeanDefinitionParser.parse()

    public BeanDefinition parse(Element element, ParserContext parserContext) {        registerTransactionalEventListenerFactory(parserContext);        //对<tx:annotation-driven/> 标签的mode属性进行判断        String mode = element.getAttribute("mode");        if ("aspectj".equals(mode)) {            // mode="aspectj"  提供对aspectj方式进行事务的支持            registerTransactionAspect(element, parserContext);        }        else {            // mode="proxy"            AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);        }        return null;    }

AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {        //1.表示<tx:annoation-driven/>标签只会被解析一次,只有第一次才剩下          AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);?            String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;            if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {                Object eleSource = parserContext.extractSource(element);?                // Create the TransactionAttributeSource definition.               //2.创建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.                //3.创建TransactionInterceptor                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.                //4.创建BeanFactoryTransactionAttributeSourceAdvisor,并把前2个添加到属性中                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);            }

上面注册的三个Bean支持了整个事务的功能

registerAutoProxyCreatorIfNecessary()

    public static void registerAutoProxyCreatorIfNecessary(            ParserContext parserContext, Element sourceElement) {        //注册InfrastructureAdvisorAutoProxyCreator        BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(                parserContext.getRegistry(), parserContext.extractSource(sourceElement));        //设置proxy-target-class和expose-proxy的配置        useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);        registerComponentIfNecessary(beanDefinition, parserContext);    }

这两个方法的主要目的是注册InfrastructureAdvisorAutoProxyCreator ,这个类间接实现了BeanPostProcessor接口,我们知道,Spring会保证所有bean在实例化的时候都会调用其postProcessAfterInitialization方法,我们可以使用这个方法包装和改变bean,而真正实现这个方法是在其父类AbstractAutoProxyCreator类中:

//实例化userService的Bean就会调用此方法

postProcessAfterInitialization()

    @Override    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {        if (bean != null) {            //根据给定的Bean的class和name构建出key            Object cacheKey = getCacheKey(bean.getClass(), beanName);            if (!this.earlyProxyReferences.contains(cacheKey)) {                return wrapIfNecessary(bean, beanName, cacheKey);            }        }        return bean;    }

wrapIfNecessary()

    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;        }?        // Create proxy if we have advice.        //获取指定Bean对应的增强器        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);        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;        }?        this.advisedBeans.put(cacheKey, Boolean.FALSE);        return bean;    }

registerTransactionManager()

    private static void registerTransactionManager(Element element, BeanDefinition def) {        def.getPropertyValues().add("transactionManagerBeanName",                TxNamespaceHandler.getTransactionManagerName(element));    }

getTransactionManagerName(element));

tx:annotation-driven/不指定属性的时候,默认去找id固定名为transactionManager的bean作为事务管理器

tatic final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";

	static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";

	static String getTransactionManagerName(Element element) {
		return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
				element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
	}

原文地址:https://www.cnblogs.com/itxiaok/p/10356685.html

时间: 2024-10-22 14:06:50

Spring事务源码分析总结的相关文章

spring事务源码分析结合mybatis源码(一)

最近想提升,苦逼程序猿,想了想还是拿最熟悉,之前也一直想看但没看的spring源码来看吧,正好最近在弄事务这部分的东西,就看了下,同时写下随笔记录下,以备后查. spring tx源码分析 这里只分析简单事务也就是DataSourceTransactionManager 首先肯定找入口了,看过spring源码的同学一定都会找spring tx的入口就是在TxAdviceBeanDefinitionParser这里将解析tx的配置,生成TransactionInterceptor对象,这个也就是一

Spring 事务源码分析——Hibernate篇

在Spring与Hibernate整合的时候,可以利用Spring的事务管理机制,为我们管理事务的开启.提交.回滚等操作.这样的方式极大的减少了我们的代码量,让我们只专注于业务代码的编写.在使用Hibernate的时候,每一个操作都要经历事务开启与提交这样的操作,他们在业务代码的周围,这样来看是不是就想到了AOP编程,把这部分代码抽取出来.没错,Spring正是这样做的,Spring的事务管理就是基于AOP的. 1 Spring的事务隔离与传播 Srping的事务定义了五个隔离等级(isolat

spring事务源码分析结合mybatis源码(三)

下面将结合mybatis源码来分析下,这种持久化框架是如何对connection使用,来达到spring事务的控制. 想要在把mybatis跟spring整合都需要这样一个jar包:mybatis-spring-x.x.x.jar,这里面定义了一些主要的整合信息. 在spring配置文件中需要配置如下两个bean: <!-- mybatis配置 --> <bean id="sqlSessionFactory" class="org.mybatis.sprin

Spring事务源码分析

首先看例子,这例子摘抄自开涛的跟我学spring3. @Test public void testPlatformTransactionManager() { DefaultTransactionDefinition def = new DefaultTransactionDefinition(); def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); def.setPropagationBehavior(T

spring事务源码分析结合mybatis源码(二)

让我们继续上篇,分析下如果有第二个调用进入的过程. 代码部分主要是下面这个: if (isExistingTransaction(transaction)) { return handleExistingTransaction(definition, transaction, debugEnabled); } protected boolean isExistingTransaction(Object transaction) { DataSourceTransactionObject txOb

spring事务源码研读1

转载摘录自:Spring事务源码分析(一)Spring事务入门 有时为了保证一些操作要么都成功,要么都失败,这就需要事务来保证. 传统的jdbc事务如下: @Test public void testAdd(){ Connection con=null; try { con=DriverManager.getConnection(url , username , password ) con.setAutoCommit(false); //操作一 PreparedStatement ps = c

Spring AMQP 源码分析 05 - 异常处理

### 准备 ## 目标 了解 Spring AMQP Message Listener 如何处理异常 ## 前置知识 <Spring AMQP 源码分析 04 - MessageListener> ## 相关资源 Offical doc:<http://docs.spring.io/spring-amqp/docs/1.7.3.RELEASE/reference/html/_reference.html#exception-handling> Sample code:<ht

Spring AMQP 源码分析 07 - MessageListenerAdapter

### 准备 ## 目标 了解 Spring AMQP 如何用 POJO 处理消息 ## 前置知识 <Spring AMQP 源码分析 04 - MessageListener> ## 相关资源 Offical doc:<http://docs.spring.io/spring-amqp/docs/1.7.3.RELEASE/reference/html/_reference.html#message-listener-adapter> Sample code:<https:

Spring AMQP 源码分析 06 - 手动消息确认

### 准备 ## 目标 了解 Spring AMQP 如何手动确认消息已成功消费 ## 前置知识 <Spring AMQP 源码分析 04 - MessageListener> ## 相关资源 Offical doc:<http://docs.spring.io/spring-amqp/docs/1.7.3.RELEASE/reference/html/_reference.html#message-listener-adapter> Sample code:<https: