Spring事务解析2-标签解析

根据自定义标签的使用规则,可以知道会执行AnnotationDrivenBeanDefinitionParser的parse

    @Override
    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属性的判断,根据配置,选择以动态织入还是静态织入。以下分析以proxy方式织入。

注册InfrastructureAdvisorAutoProxyCreator

private static class AopAutoProxyConfigurer {
    public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
        AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
        //TRANSACTION_ADVISOR_BEAN_NAME ="org.springframework.transaction.config.internalTransactionAdvisor";
        String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
        if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
            Object eleSource = parserContext.extractSource(element);
            //创建TransactionAttributeSource的bean
            RootBeanDefinition sourceDef = new RootBeanDefinition(
                    "org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
            sourceDef.setSource(eleSource);
            sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            //注册bean,并使用Spring中的定义规则生成beanname
            String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
            //创建TransactionInterceptor的bean
            RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
            interceptorDef.setSource(eleSource);
            interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            registerTransactionManager(element, interceptorDef);
            interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
            //注册bean,并使用Spring中的定义规则生成beanname
            String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);
            //如果配置了order属性,则加入到bean中
            //创建TransactionAttributeSourceAdvisor的bean
            RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
            advisorDef.setSource(eleSource);
            advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            //将sourceName的bean注入advisorDef的transactionAttributeSource属性中
            advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
            //将interceptorName的bean注入advisorDef的adviceBeanName属性中
            advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
            if (element.hasAttribute("order")) {
                advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
            }
            parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);
            //创建CompositeComponentDefinition
            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,这三个bean支撑了整个的事务功能,那么这三个bean是怎么组织起来的呢?

其中的两个bean被注册到了一个名为advisorDef的bean中,advisorDef使用BeanFactoryTransactionAttributeSourceAdvisor作为其class属性。也就是说BeanFactoryTransactionAttributeSourceAdvisor代表着当前bean。

上面函数configureAutoProxyCreator中的第一句貌似很简单但却是很重要的代码:

AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

    public static void registerAutoProxyCreatorIfNecessary(
            ParserContext parserContext, Element sourceElement) {
        BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
                parserContext.getRegistry(), parserContext.extractSource(sourceElement));
        useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
        registerComponentIfNecessary(beanDefinition, parserContext);
    }

对于解析来的代码流程AOP中已经有所分析,上面的两个函数主要目的是注册了InfrastructureAdvisorAutoProxyCreator类型的bean,那么注册这个类的目的是什么呢?

    public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
        return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
    }
时间: 2024-10-14 10:05:14

Spring事务解析2-标签解析的相关文章

Spring源码解析——自定义标签解析

再讲解析自定义标签之前,先要知道怎么实现自定义标签的,接下来就来看下吧. 1.第一步,定义一个实体类,如图1: 图1 2.第二步,定义一个xsd(xsd是什么不知道的自行百度),如图2: 图2 3.第三步,生成spring.handlers和spring.schemas文件,一定要放在resources/META-INF下面,因为解析的时候只会到这个目录下面去找,先看下spring.handlers,如图3: 图3 在看下spring.schemas,如图4: 图4 4.第四步,实现Abstra

phpcms模板解析嵌套标签解析失败

PHPCMS的模板解析函数是/phpcms/libs/classes/template_cache.class.php这个类中的template_parse函数. 我把这个文件拿出来,然后在下面直接写上 $str = '{php echo 1} -- {$abc}';$template = new template_cache();echo $c = $template->template_parse($str); 这时输出的是 <?php defined('IN_PHPCMS') or ex

Spring事务解析3-增强方法的获取

从InfrastructureAdvisorAutoProxyCreator的层次结构中可以看到,InfrastructureAdvisorAutoProxyCreator间接实现了SmartInstantiationAwareBeanPostProcessor,而SmartInstantiationAwareBeanPostProcessor又继承自InstantiationAwareBeanPostProcessor,也就是说在Spring中,所有bean实例化时Spring都会保证调用其p

spring与ibatis集成之事务部分源码解析

ibatis是一个非常优秀的半自动ORM框架,相较于许多人认为编写sql和配置字段映射会降低开发效率,我认为在数据库最易成为系统瓶颈的情况下,开发人员必须通过手动编写sql来保证sql执行的高效,并在编写过程中思考表结构的设计是否合理.网上已有许多关于ibatis架构和映射实现原理解析的文章,本文主要讨论ibatis和spring集成后事务管理的实现.在spring和ibatis集成后,有两种方式执行sql:第一种是dao继承spring的SqlMapClientDaoSupport,具体的sq

spring源码剖析(二)Spring默认标签解析及注册实现

在使用spring的时候,我也经常会使用到bean标签,beans标签,import标签,aop标签等. 下面主要为读者介绍spring的默认的自带标签的解析流程. 验证模式(DTD&XSD) dtd基本已被淘汰,现在spring的验证模式基本都是采用xsd文件作为xml文档的验证模式,通过xsd文件可以检查该xml是否符合规范,是否有效.在使用xsd文件对xml文档进行校验的时候,除了要名称空间外(xmlns="http://www.springframework.org/schema

Spring事务管理—aop:pointcut expression解析

先来看看这个spring的配置文件的配置: <!-- 事务管理器 -->  <bean id="transactionManager"   class="org.springframework.orm.hibernate3.HibernateTransactionManager">   <property name="sessionFactory" ref="sessionFactory" /&g

Spring事务源码解析(二)获取增强

在上一篇文章@EnableTransactionManagement注解解析中,我们搭建了源码阅读的环境,以及解析了开启Spring事务功能的注解@EnableTransactionManagement的实现逻辑 在进行接下来的源码解析之前我想大家应该知道,当我们使用传统的jdbc应用事务的时候是不是做了如下操作: 开启事务 save.update.delete等操作 出现异常进行回滚 正常情况提交事务 而在Spring中我们好像只需要关心第三步,也就是我们的业务,而其他的操作都不需要关心.那么

Mybaits 源码解析 (十二)----- Mybatis的事务如何被Spring管理?Mybatis和Spring事务中用的Connection是同一个吗?

不知道一些同学有没有这种疑问,为什么Mybtis中要配置dataSource,Spring的事务中也要配置dataSource?那么Mybatis和Spring事务中用的Connection是同一个吗?我们常用配置如下 <!--会话工厂 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name=&qu

spring事务解析

1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必须是要么都执行要么都不执行.如果银行卡扣除了1000块但是ATM出钱失败的话,你将会损失1000元:如果银行卡扣钱失败但是ATM却出了1000块,那么银行将损失1000元.所以,如果一个步骤成功另一个步骤失败对双方都不是好事,如果不管哪一个步骤失败了以后,整个取钱过程都能回滚,也就是完全取消所有操作的话

一文解析Spring事务管理详解;通俗易懂,轻松掌握!

事务概念回顾 什么是事务? 事务是逻辑上的一组操作,要么都执行,要么都不执行. 事物的特性(ACID): 原子性:?事务是最小的执行单位,不允许分割.事务的原子性确保动作要么全部完成,要么完全不起作用: 一致性:?执行事务前后,数据保持一致: 隔离性:?并发访问数据库时,一个用户的事物不被其他事物所干扰,各并发事务之间数据库是独立的: 持久性:?一个事务被提交之后.它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响. Spring事务管理接口介绍 Spring事务管理接口: