Spring事物之——AbstractSingletonProxyFactoryBean

    接下来的几篇文章我们要讨论一下Spring事物的实现原理。在讨论Spring事物的过程中,我们以分析Spring事物中几个关键类的方式来了解Spring事物是如何实现的。本文的基础是建立在对Spring Aop有深入理解的前提下,如果小伙伴们对Spring Aop的原理有疑问,请看一下《Spring AOP --JDK动态代理方式》这边文章。
    言归正传,我们来看一下本篇文章的重点,也是分析Spring事物过程中的第一个关键类:AbstractSingletonProxyFactoryBean。从类名上,我们可以猜的出AbstractSingletonProxyFactoryBean是一个抽象类,实现了FactoryBean。对Spring比较熟悉的小伙伴们应该对FactoryBean不陌生,希望大家能知道FactoryBean的区别,这里我们就不多说了,不清楚的小伙伴可以查一下其他资料。我们可以从AbstractSingletonProxyFactoryBean的定义证实我们的猜想:

public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
        implements FactoryBean<Object>, BeanClassLoaderAware, InitializingBean

既然AbstractSingletonProxyFactoryBean实现了FactoryBean接口,我们就来看一下FactoryBean的getObject()方法,看一下AbstractSingletonProxyFactoryBean是什么对象的工厂:

    public Object getObject() {
        if (this.proxy == null) {
            throw new FactoryBeanNotInitializedException();
        }
        return this.proxy;
    }

getObject() 方法返回的是AbstractSingletonProxyFactoryBean本身持有的proxy对象,这个对象是怎么产生的,我们可以看到proxy对象是在afterPropertiesSet()方法中赋值的,afterPropertiesSet()方法是InitializingBean接口的方法,InitializingBean接口是一个Bean在生命周期中的一个重要的接口,实现了这个接口的Bean在实例化属性赋值完之后,spring会调用其afterPropertiesSet()方法作为钩子方法。我们先来看看AbstractSingletonProxyFactoryBean的afterPropertiesSet()做了哪些事情:

    @Override
    public void afterPropertiesSet() {
        if (this.target == null) {
            throw new IllegalArgumentException("Property 'target' is required");
        }
        if (this.target instanceof String) {
            throw new IllegalArgumentException("'target' needs to be a bean reference, not a bean name as value");
        }
        if (this.proxyClassLoader == null) {
            this.proxyClassLoader = ClassUtils.getDefaultClassLoader();
        }
        //创建一个ProxyFactory 对象
        ProxyFactory proxyFactory = new ProxyFactory();
        //设置代理工厂要产生的代理的前置通知
        if (this.preInterceptors != null) {
            for (Object interceptor : this.preInterceptors) {
                proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor));
            }
        }

        // Add the main interceptor (typically an Advisor).添加一个通知,createMainInterceptor()是一个抽象方法,交给子类实现
        proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor()));
        //设置代理工厂要产生的代理的后置通知
        if (this.postInterceptors != null) {
            for (Object interceptor : this.postInterceptors) {
                proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor));
            }
        }

        proxyFactory.copyFrom(this);

        TargetSource targetSource = createTargetSource(this.target);
        proxyFactory.setTargetSource(targetSource);

        if (this.proxyInterfaces != null) {
            proxyFactory.setInterfaces(this.proxyInterfaces);
        }
        else if (!isProxyTargetClass()) {
            // Rely on AOP infrastructure to tell us what interfaces to proxy.
            proxyFactory.setInterfaces(
                    ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(), this.proxyClassLoader));
        }
        //产生对象的前置方法,这里是个空方法,子类可以通过实现这个方法来改变proxyFactory的配置
        postProcessProxyFactory(proxyFactory);

        this.proxy = proxyFactory.getProxy(this.proxyClassLoader);
    }

    看过《Spring AOP --JDK动态代理方式》这边文章的同学对ProxyFactory应该不会陌生,ProxyFactory能够根据配置的代理对象、通知(Advice)来生成代理对象。这一点清楚后我们再回过头来看一下afterPropertiesSet()究竟干了什么。首先,方法创建了一个ProxyFactory的对象。然后将AbstractSingletonProxyFactoryBean设置的前置通知添加到ProxyFactory的通知链中。然后通过createMainInterceptor()获得一个通知,将该通知添加到通知链中。createMainInterceptor()是一个抽象方法,由子类去实现。随后,又将AbstractSingletonProxyFactoryBean设置的后置通知添加到ProxyFactory的通知链中。做完通知链添加动作之后,又将AbstractSingletonProxyFactoryBean配置的各种属性赋值到proxyFactory中,具体哪些属性这里不多说了。做完这一系列动作之后,又调用了 postProcessProxyFactory(proxyFactory);方法,这个方法是一个模板方法,作为proxyFactory产生代理对象前的前置方法,提供修改proxyFactory的机会。最后通过调用proxyFactory的getProxy(ClassLoader classLoader)方法产生代理对象。
    到这里我们看到了Spring设计中经常使用的一种设计模式,模板模式。afterPropertiesSet()方法其实为AbstractSingletonProxyFactoryBean提供了产生proxy对象的模板,而proxy代理对象的通知是由子类产生的。在产生代理对象之前,模板方法通过开放postProcessProxyFactory(ProxyFactory proxyFactory)方法,给子类修改代理对象配置的机会。AbstractSingletonProxyFactoryBean生成完proxy对象之后就会一直持有该对象,等待调用者调用工厂方法。
    我们来总结一下AbstractSingletonProxyFactoryBean的作用:AbstractSingletonProxyFactoryBean作为一个单例工厂,定义了产生代理对象的模板,AbstractSingletonProxyFactoryBean产生的代理对象的具体代理内容交由子类定义。
    AbstractSingletonProxyFactoryBean的具体作用和原理我们分析完了,Spring事物其实是通过AbstractSingletonProxyFactoryBean定义的模板来实现事物代理对象创建的。具体细节我们在接下里的几篇文章中会继续讨论。本篇内容很简单,也可以作为之前Spring相关文章的一个复习内容。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,654评论 18 139
  • 什么是Spring Spring是一个开源的Java EE开发框架。Spring框架的核心功能可以应用在任何Jav...
    jemmm阅读 16,462评论 1 133
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,808评论 6 342
  • 本博中关于spring的文章:Spring IOC和AOP原理,Spring事务原理探究,Spring配置文件属性...
    Maggie编程去阅读 4,103评论 0 34
  • 持久化存储 关键概念: 文件系统,数据库系统文件系统中,大量文件没有很好组织,缺乏对象之间关键,读取效率低,因此有...
    _Hook_阅读 2,405评论 0 4