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);
    	}
    
    
  • 相关阅读:
    String的转换问题
    springmvc maven搭建一
    top 使用心得
    spring 之AOP 和继承方法
    xml语法
    tomcat 相关
    json之注意
    javaScript 中创建json/转换字符串为json
    java基础之继承
    vim复制,删除
  • 原文地址:https://www.cnblogs.com/itxiaok/p/10356685.html
Copyright © 2011-2022 走看看