Spring事务切面原理

一、前言

本节我们来谈谈 <tx:advice/>、<aop:config> 标签如何创建事务切面的。

二、<tx:advice/>、<aop:config> 标签如何创建事务切面的

<tx:advice/>标签作用是创建一个TransactionInterceptor,作为事务切面的通知方法。在Spring中(可以参考:https://gitbook.cn/gitchat/activity/5a8fdf6bf2e5dc2ca621a937) Advisor这个概念是从 Spring 1.2的 AOP 支持中提出的,一个 Advisor 相当于一个小型的切面,不同的是它只有一个通知(Advice),Advisor中还包含一个pointcut(切点),切点定义了对那些方法进行拦截,而通知是具体对拦截到的方法进行增强的逻辑。

具体对<tx:advice/>标签进行解析的是TxAdviceBeanDefinitionParser,其时序图如下:

enter image description here

首先TxAdviceBeanDefinitionParser有getBeanClass方法代码代码:

    protected Class<?> getBeanClass(Element element) {
        return TransactionInterceptor.class;
    }

这说明该标签解析后生成的是TransactionInterceptor对象的bean定义。

  • 其中时序图中步骤(2)是设置配置demo的XML配置文件里面创建的事务管理器到TransactionInterceptor对象,

image.png

  • 时序图(4)~(10)则解析<tx:advice/>标签中事务属性值设置到TransactionInterceptor对象里面属性里面。

注:也就是<tx:advice/>标签的作用是生成一个TransactionInterceptor拦击器对象,并设置该对象的一些事务属性,然后该对象将作为事务切面的通知方法。

<aop:config>标签作用是创建一个DefaultBeanFactoryPointcutAdvisor(其实现了Advisor接口)对象作为作一个Advisor,前面说了一个Advisor就是一个小型的切面,所以其中定义了切点和通知。该标签是ConfigBeanDefinitionParser类进行解析的,其时序图如下:

enter image description here

  • 时序图中步骤(2)创建了一个DefaultBeanFactoryPointcutAdvisor对象的bean定义,步骤(3)(4)则是设置上面创建的通知对象(TransactionInterceptor)到该Advisor
  • 时序图中步骤(8)则是解析标签中的切点表达式,然后设置到DefaultBeanFactoryPointcutAdvisor对象的bean定义。
  • 时序图步骤(4)注册了一个AspectJAwareAdvisorAutoProxyCreator到Spring容器,作用就是对满足pointcut表达式的类的方法进行代理,并且使用advice进行拦截处理,而advice就是事务拦截器。

由于AspectJAwareAdvisorAutoProxyCreator类实现了BeanPostProcessor接口,所以具有postProcessAfterInitialization方法,而对符合切点的方法进行代理就是在该方法内的wrapIfNecessary方法:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        ...
        // 8.1
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            //8.2
            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;
    }

其中8.1查找所有可以对当前bean进行增强的切面,其中有一个条件就是看那些bean实现了Advisor接口,而<aop:config>标签作用是创建一个DefaultBeanFactoryPointcutAdvisor,并且其实现了Advisor接口,所以这里会使用DefaultBeanFactoryPointcutAdvisor切面,然后会看当前bean的方法是否满足切面的切点表达式,具体是AopUtils的canApply方法进行判断:

image.png

如果满足则执行8.2对方法进行代理,这里会对TestTransactionProgagationUserImpl、TestTransactionProgagationCourseImpl、UserManagerBoImpl类的所有方法进行事务代理。

注:Spring框架中一个 Advisor 相当于一个小型的切面,<tx:advice/>定义了这个切面的通知方法,而<aop:config>具体定义了一个Advisor切面,并且内部定义了一个切点,并且引入了<tx:advice/>定义的通知方法

最后

更多本地事务咨询可以单击我 更多分布式事务咨询可以单击我 更多Spring事务配置解惑单击我

想了解更多关于粘包半包问题单击我 更多关于分布式系统中服务降级策略的知识可以单击 单击我 想系统学dubbo的单击我 想学并发的童鞋可以 单击我

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏代码拾遗

OkHttp 使用示例

可以用来下载文件,打印header,打印body。string()方法对于小文档的响应来说是个既方便又高效的方法。但是如果一个文档太大(大于1M),就不要使用s...

32610
来自专栏java思维导图

Spring思维导图,让Spring不再难懂(aop篇)

什么是aop AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing...

37370
来自专栏青玉伏案

ObjC中的AOP--面向切面编程

上篇博客我们类比着Java的Spring框架中的依赖注入的实现方式,也试着使用Objective-C来写了一下OC中的依赖注入的实现方式。当然,我们是使用的PL...

21860
来自专栏Android 研究

OkHttp源码解析(十) OKHTTP中连接与请求及总结

主要看下ConnectInterceptor()方法,里面代码已经很简单了,受限了通过streamAllocation的newStream方法获取一个流(Htt...

19140
来自专栏分布式系统和大数据处理

从一个范例看XML的应用

如果你已经看了《Asp.Net Ajax的两种基本开发模式》 这篇文章,你可能很快会发现这样一个问题:在那篇文章的方式2中,客户端仅仅是发送了页面上一个文本框的...

13340
来自专栏Java架构沉思录

Spring AOP失效之谜

什么是AOP 1 AOP(Aspect Oriented Programming),即面向切面编程,其是OOP(Object Oriented Program...

43890
来自专栏Java成神之路

Java之网络编程笔记

  IP地址:用于标记一台计算机的身份证。 IP地址由网络地址(确定网络)和主机地址(网络中的主机)组成。

11420
来自专栏java初学

II 3.1 连接到服务器

431110
来自专栏西安-晁州

rabbitmq消息队列——"topic型交换器"

在之前的章节中我们改进了我们的日志系统,我们使用direct型交换器代替了只能盲目广播消息的fanout型交换器,这使得我们可以有选择性地接收日志。 尽管使用d...

21700
来自专栏技术小讲堂

ASP.NET AJAX(1)__Microsoft AJAX LibraryASP.NET AJAX(1)__Microsoft AJAX Library

ASP.NET AJAX(1)__Microsoft AJAX Library Microsoft AJAX Library为我们提供的客户端框架,提供的内容大...

29740

扫码关注云+社区

领取腾讯云代金券