在上一章节中,我们知道了Spring是如何去获取单例bean,而这一章节我们将要去了解Spring是如何从bean获取对象。(相关资源可到这里下载:http://pan.baidu.com/s/1sjSo9a9)

在最开始前面我们知道了,Spring的获取bean的方法的入口函数是getObjectForBeanInstance。那么我们就跟着时序图一步一步赶往代码查看。

1)        首先,我们要看在是getObjectForInstance的函数,这个函数主要做的事情是:

a)        对FactoryBean正确的验证

b)        对非FactoryBean不做任何处理

c)        对bean进行转换

d)        将从Factory中解析bean的工作委托给getObjectFromFactoryBean

 protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {// Don't let calling code try to dereference the factory if the bean isn't a factory.//如果指定的name是工厂相
关(以&为前缀)且beanInstance又不是FactoryBean类型则验证不通过if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());}// Now we have the bean instance, which may be a normal bean or a FactoryBean.// If it's a FactoryBean, we use it to create a bean instance, unless the// caller actually wants a reference to the factory.//现在我们有了bean的实例,这个实例可能会是正常的bean或者是FactoryBean//如果是FactoryBean我们使用它创建实例,但是如果是用户想要获取工厂实例而不是工厂的//getObject方法对应 的实例,那么传入的name应该加入前缀if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {return beanInstance;}//加载FactoryBeanObject object = null;if (mbd == null) {//尝试从缴存中加载beanobject = getCachedObjectForFactoryBean(beanName);}if (object == null) {// Return bean instance from factory.//到这里已经明确知道beanInstance一定是FactoryBean类型FactoryBean<?> factory = (FactoryBean<?>) beanInstance;// Caches object obtained from FactoryBean if it is a singleton.//containsBeanDefinition检测beanDefinitionMap中也就是在所有已经加载的类中检测是否定义beanNameif (mbd == null && containsBeanDefinition(beanName)) {//将存储XML配置文件的GenericBeanDfinition转换为RootBeanDefinition,如果指定BeanName是子Bean的话同时会合并父类的相关属性mbd = getMergedLocalBeanDefinition(beanName);}//是否是用户定义的而不是应用程序本身定义的boolean synthetic = (mbd != null && mbd.isSynthetic());object = getObjectFromFactoryBean(factory, beanName, !synthetic);}return object;}

2)        我们继续跟踪代码到getObjectFromFactoryBean().

 protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {//如果是单例模式if (factory.isSingleton() && containsSingleton(beanName)) {synchronized (getSingletonMutex()) {Object object = this.factoryBeanObjectCache.get(beanName);if (object == null) {object = doGetObjectFromFactoryBean(factory, beanName);// Only post-process and store if not put there already during getObject() call above// (e.g. because of circular reference processing triggered by custom getBean calls)Object alreadyThere = this.factoryBeanObjectCache.get(beanName);if (alreadyThere != null) {object = alreadyThere;}else {if (object != null && shouldPostProcess) {try {object = postProcessObjectFromFactoryBean(object, beanName);}catch (Throwable ex) {throw new BeanCreationException(beanName,"Post-processing of FactoryBean's singleton object failed", ex);}}this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));}}return (object != NULL_OBJECT ? object : null);}}else {Object object = doGetObjectFromFactoryBean(factory, beanName);if (object != null && shouldPostProcess) {try {object = postProcessObjectFromFactoryBean(object, beanName);}catch (Throwable ex) {throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);}}return object;}}

3)        在上面的方法中,我们比较关心的是doGetObjectFromFactoryBean ()的方法,这个方法中有一行代码是:object = factory.getObject(),这似乎是我们想要看到的。

private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)throws BeanCreationException {Object object;try {//需要权限验证if (System.getSecurityManager() != null) {AccessControlContext acc = getAccessControlContext();try {object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {@Overridepublic Object run() throws Exception {return factory.getObject();}}, acc);}catch (PrivilegedActionException pae) {throw pae.getException();}}else {//直接调用getObject方法object = factory.getObject();}}catch (FactoryBeanNotInitializedException ex) {throw new BeanCurrentlyInCreationException(beanName, ex.toString());}catch (Throwable ex) {throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);}// Do not accept a null value for a FactoryBean that's not fully// initialized yet: Many FactoryBeans just return null then.if (object == null && isSingletonCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");}return object;}

4)        方法中的object = factory.getObject()得到了我们想要的结果,但是并没有直接返回,我们继续到getObjectFromFactoryBean方法的postProcessObjectFromFactoryBean方法下,再进入applyBeanPostprocessorsAfterInitiallization()的方法,就可以得到结果了。

@Overrideprotected Object postProcessObjectFromFactoryBean(Object object, String beanName) {return applyBeanPostProcessorsAfterInitialization(object, beanName);}
@Overridepublic Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {result = beanProcessor.postProcessAfterInitialization(result, beanName);if (result == null) {return result;}}return result;}

Spring源码之bean的加载(三)从bean中获取对象相关推荐

  1. Spring源码解析-applicationContext.xml加载和bean的注册

    applicationContext文件加载和bean注册流程 ​ Spring对于从事Java开发的boy来说,再熟悉不过了,对于我们这个牛逼的框架的介绍就不在这里复述了,Spring这个大杂烩,怎 ...

  2. 【框架源码】Spring源码解析之BeanDefinition加载流程解析

    观看本文之前,我们先思考一个问题,Spring是如何描述Bean对象的? Spring是根据BeanDefinition来创建Bean对象,BeanDefinition就是Spring中表示Bean定 ...

  3. Spring源码之BeanDifinition(加几行代码,可以产出让队友几天也找不出的Bug)

    前言 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin392328206/six-finger 种一棵树最好的时间是十年前,其次是现在 我知道很多人不玩qq ...

  4. Android 11.0 Settings源码分析 - 主界面加载

    Android 11.0 Settings源码分析 - 主界面加载 本篇主要记录AndroidR Settings源码主界面加载流程,方便后续工作调试其流程. Settings代码路径: packag ...

  5. android资源加载流程6,FrameWork源码解析(6)-AssetManager加载资源过程

    之前一段时间项目比较忙所以一直没有更新,接下来准备把插件化系列的文章写完,今天我们就先跳过ContentProvider源码解析来讲资源加载相关的知识,资源加载可以说是插件化非常重要的一环,我们很有必 ...

  6. 有没有code能改xml内容_Spring源码解析-applicationContext.xml加载和bean的注册

    applicationContext文件加载和bean注册流程 ​ Spring对于从事Java开发的boy来说,再熟悉不过了,对于我们这个牛逼的框架的介绍就不在这里复述了,Spring这个大杂烩,怎 ...

  7. JVM源码阅读-本地库加载流程和原理

    前言 本文主要研究OpenJDK中JVM源码中涉及到native本地库的加载流程和原理的部分.主要目的是为了了解本地库是如何被加载到虚拟机,以及是如何找到并执行本地库里的本地方法,以及JNI的 JNI ...

  8. 从源码解析-结合Activity加载流程深入理解ActivityThrad的工作逻辑

    ActivityThread源码解析 前言 类简称 类简介 一 二 三 四 五 代理和桩的理解 ActivityThread ActivityThread.main AT.attach AMN.get ...

  9. 【Android源码】Activity如何加载布局

    我们都知道在Activity中通过setContentView(layoutId)来加载布局文件,使我们的布局文件能够显示在手机上,那么系统是如何将我们的布局文件加载到界面上的呢? setConten ...

  10. LoadingCache源码剖析之缓存加载实现

    其他文章:https://blog.csdn.net/define_us/article/details/111656019 随着互联网的发展,数据量不断增长,用户对性能要求的不断提升,在开发项目中使 ...

最新文章

  1. 18,rand('state',sum(100*clock))
  2. 十问十答 Apache 许可证
  3. dump分析工具_Java应用CPU过高,如何排查?参考解决思路和常用工具总结
  4. 快速上手,使用 Kotlin 把支付宝小程序装进自己的 App
  5. HTML5响应式品牌服装设计类织梦模板
  6. 什么是ITSS认证,需要多长时间
  7. linux :Tar 命令参数详解
  8. HC蓝牙模块测试AT指令搭建外部电路遇到的问题
  9. 发力多人在线游戏!PS5有望2020年E3展会亮相!
  10. tiledmap 图块属性_TiledMap地图使用
  11. JS地图经纬度正则表达式校验
  12. 2022程序员必备网站
  13. C语言标准ANSI C、C语言的特点、C语言的关键字(32个)
  14. 人工智能机器人标准化建设的意义
  15. Zigbee Zstack2.5.1a使用rfx2401+cc2530
  16. Android程序员在大厂工作是什么体验?
  17. 图中的搜索——dij
  18. android 放大镜 Magnifier 简单实现
  19. PN532和控制器之间的交互
  20. 基于QT的多媒体播放器

热门文章

  1. 简单易用的安装文件制作工具NSIS的使用demo示例
  2. yourphp超出20记录自动删除
  3. JavaScript验证表单大全【自用】
  4. Kubernetes详解(十七)——Pod存活性探针应用实战
  5. Tomcat详解(三)——tomcat多实例
  6. LAMP架构调优(十)——Apache禁止指定目录PHP解析与错误页面优化
  7. QoS队列调度技术详解
  8. ansible 第二次练习
  9. 成绩排序--清华机试真题;使用运算符重载
  10. 音视频开发(Anychat如何改善音视频通话过程中的用户体验)