zoukankan      html  css  js  c++  java
  • 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

    @Override
    public 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);
    	}
    
    
  • 相关阅读:
    消息中间件(一)MQ详解及四大MQ比较
    SIP协议
    PAT (Basic Level) Practice 1008 数组元素循环右移问题
    LeetCode-Algorithms 1. 两数之和
    PAT (Basic Level) Practice 1040 有几个PAT
    PAT (Basic Level) Practice 1023 组个最小数
    PAT (Basic Level) Practice 1021 个位数统计
    PAT (Basic Level) Practice 1007 素数对猜想
    PAT (Basic Level) Practice 1006 换个格式输出整数
    PAT (Basic Level) Practice 1004 成绩排名
  • 原文地址:https://www.cnblogs.com/itxiaok/p/10356685.html
Copyright © 2011-2022 走看看