Spring Ioc中Bean加载的方法


本篇内容主要讲解“Spring Ioc中Bean加载的方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring Ioc中Bean加载的方法”吧!在之前的文章中,我们分析了Spring的Ioc的初始化过程,实际上就是把beanNameBeanDefinition注册到DefaultListableBeanFactory的map中。
在完成 bean 的注册之后,refresh()还调用了很多后处理器的方法,其中有一个方法 finishBeanFactoryInitialization(),注释上面写着 Instantiateall remaining(non-lazy-init)singletons,意味着非延迟加载的类,将在这一步实例化,完成类的加载。
而我们使用到 context.getBean(“beanName”)方法,如果对应的 bean 是非延迟加载的,那么直接就能拿出来进行使用,而延迟加载的 bean 就需要上面的步骤进行类的加载,加载完之后才能进行使用。我们接着分析一下Ioc的bean实例化过程:当我们显示或者隐式地调用 BeanFactory#getBean(String name) 方法时,则会触发加载 Bean 阶段。代码如下:内部调用 doGetBean(String name, final Class requiredType, Object[] args, boolean typeCheckOnly) 方法,其接受四个方法参数:name :要获取 Bean 的名字requiredType :要获取 bean 的类型args :创建 Bean 时传递的参数。这个参数仅限于创建 Bean 时使用。typeCheckOnly :是否为类型检查。代码很长,需要一些耐心,下面我们来逐步分析这段代码:处:具体分析,见2.1获取原始beanName处: 具体分析,见2.2从缓存中获取单例bean处: 具体分析,见2.3获取最终的bean实例对象处: 具体分析,见2.4原型模式依赖检查处: 具体分析,见2.5标记bean为已创建或即将创建处: 具体分析,见2.6获取BeanDefinition处: 具体分析,见2.7bean依赖处理处: 具体分析,见2.8不同作用域bean的实例化处: 具体分析,见2.9类型转换代码如下:继续深入,代码如下:BeanFactoryUtils.transformedBeanName(name)方法主要是去除 FactoryBean 的修饰符ps: 如果一个factoryBean的名称为“student”,获取factoryBean创建的Bean时,使用getBean("student"),获取factoryBean本身时,使用getBean("&student")
接着深入,最终代码如下:主要是一个循环获取 beanName 的过程,例如,别名 A 指向名称为 B 的 bean 则返回 B,若 别名 A 指向别名 B,别名 B 指向名称为 C 的 bean,则返回 CSpring 对单例模式的 bean 只会创建一次。后续,如果再获取该 Bean ,则是直接从单例缓存中获取,该过程就体现在 #getSingleton(String beanName) 方法中。代码如下:这段代码很简单,流程如下:第一步,从singletonObjects中获取Bean对象第二步,如果获取不到且Bean正在创建中,从earlySingletonObjects获取Bean对象第三步,如果获取不到且允许提前创建,从singletonFactories获取FactoryBean第四步,如果不为null,则通过FactoryBean.getObject()获取Bean,然后将其加入到 earlySingletonObjects ,并且从 singletonFactories 删除,两者是互斥的,主要用来解决循环依赖的问题总结就是:从这三个Map依次去取,取不到就取下一个Map在上面的代码中又一个重要的方法isSingletonCurrentlyInCreation(beanName),代码如下:这个方法是用来判断当前Bean是否在创建中,看到是个Map,我们可以猜测,应该有一个地方在创建Bean的时候,会把正在创建的BeanName给put到这个Map中。具体我们之后将。当我们从getSingleton(beanName)拿到bean对象后,会接着调用getObjectForBeanInstance()方法,来获取最终的Bean实例。为什么这里要再获取一次Bean呢,之前明明都拿到了呀?因为我们从缓存中获取的 bean 是最原始的 Bean ,并不一定是我们最终想要的 Bean怎么办呢?调用 #getObjectForBeanInstance(…) 方法,进行处理,该方法的定义为获取给定 Bean 实例的对象,该对象要么是 bean 实例本身,要么就是 FactoryBean 创建的 Bean 对象。看代码:首先看下这个方法的流程:1、类型检查,判断是否是FactoryBean2、对非 FactoryBean 不做处理3、对 bean 进行转换4、处理 FactoryBean 类型:委托给 getObjectFromFactoryBean 方法进行处理。我们直接看第3步,走到这里,说明这个bean一定是FactoryBean类型的,再从Ioc容器中获取该beanName对应的BeanDefinition,如果不为null,且不是abstract,则调用getObjectFromFactoryBean方法获取bean实例从这里可以看出, getObjectForBeanInstance(Object beanInstance, String name, String beanName,RootBeanDefinition mbd) 方法,分成两种情况:第一种,当该实例对象为非 FactoryBean 类型,直接返回给定的 Bean 实例对象 beanInstance 。第二种,当该实例对象为FactoryBean 类型,从 FactoryBean ( beanInstance ) 中,获取 Bean 实例对象。我们接着看第二种情况:1、判断是否为单例并且缓存中存在 如果存在,则顺着1.1往下走,不存在,则走2的流程1.1、sync加锁,锁住的是singletonObjects,和其他单例锁一样,保证全局唯一1.2、从缓存factoryBeanObjectCache中获取Bean实例 如果获取不到,则调用doGetObjectFromFacto 香港云主机ryBean()方法获取,实际最后调用的是factory.getObject()方法1.3、如果需要后续处理( shouldPostProcess = true ),则进行下一步处理 postProcessObjectFromFactoryBean() 方法,对从 FactoryBean 处获取的 Bean 实例对象进行后置处理。其默认实现是直接返回 object 对象,不做任何处理。代码如下:但是子类可以重写,例如应用后处理器等。1.4、加入到 factoryBeanObjectCache 缓存中2、如果缓存中不存在,同样调用doGetObjectFromFactoryBean()获取bean实例到此,相信大家对“Spring Ioc中Bean加载的方法”有了更深的了解,不妨来实际操作一番吧!这里是开发云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

相关推荐: 如何选择win8系统的32位和64位

这篇文章将为大家详细讲解有关如何选择win8系统的32位和64位,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、从设计角度来讲32位的操作系统设计出来主要是面向普通电脑用户,而64位操作系统是针对高技能领域的用户,比如从事…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 07/27 17:46
下一篇 07/27 18:13

相关推荐