一、 三个API

// 根据name获取bean
@Override
public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);
}// 根据name获取bean,如果获取到的bean和指定类型不匹配,则抛出异常
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {return doGetBean(name, requiredType, null, false);
}// 根据name获取bean,如果是一个有参构造器生成的bean,则将参数对象注入到构造器中
@Override
public Object getBean(String name, Object... args) throws BeansException {return doGetBean(name, null, args, false);
}

二、源码

2.1. 获取name获取bean的真名,一个bean可以定义多个别名,这里会从map中递归获取到真名。  
2.2  根据beanName去单例池获取bean,如果存在直接返回。


   3. 如果单例池不存在bean,判断当前beanFactory是否有父的beanFactory,并且当前beanFactory能不能找到bean,如果当前beanFactory找到bean直接从当前beanFactory寻找后返回bean。否则则去父的bean工厂取。


   4. 真正的获取bean逻辑

4.1 根据beanName得到合并后的beanDefinition

4.2 判断得到的beanDefinition是否是抽象bean,是则抛异常

5. 判断beanDefinition有没有@dependentOn注解,如果有,则判断被依赖的对象是否又依赖了当前beanDefinition,即出现了自定义的循环依赖,如果是则抛异常。
   6. 如果有@dependentOn但没有循环依赖,则将依赖的对象加入dependentOnMap中,dep为key你,beanName为value。再接着先完成依赖对象的getbean();

7. 根据合并后的beanDefinition的作用域来真正创建bean对象。

7.1 如果是单例bean,创建bean后将bean添加到单例池。

7.2 如果是原型bean,创建bean后将直接返回。

7.3 其他类型的作用域如request、session等则是基于HttpRequest、HttpSession等来实现bean的存储的。

三、createBean源码

3.1. 加载类
   3.2. 将合并后的beanDefinition的Beanclass属性设置为加载的类。


   3. 进行实例化前操作:有定义实现了InstantiationAwareBeanPostProcessor接口的实现类,则可对每个对象进行实例化前操作,即调用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation(),如果实例化前方法有返回对象,则直接返回,否则进入下一步。

 

4. 实例化:
    4.1 判断当前bean是否已在别的bean创建过程中被创建了(被别的bean依赖注入)。如果没有则真正的创建bean。
    4.2 推断构造方法:
   5. 判断是否有实现了MergedBeanDefinitionPostProcessor.postProcessMergedInstantiation(),如果有通过它来修改beanDefinition的值。

 
   5. 进行实例化后操作:有定义InstantiationAwareBeanPostProcessor接口的实现类,则可对每个对象进行实例化后操作,即调用InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(),如果实例化后方法返回false,则直接返回,否则进入下一步。

6. 属性的依赖注入:
    6.1 执行spring自带的属性注入,即@Bean(Autowired.BY_NAME)这种。Autowired.BY_NAME是根据set方法名去找。


    6.2 执行@Autowired、@Resource、@Value注解,如果到这一步之前已经给属性赋值了则跳过这一步,因为有可能程序员手动赋值了。没有则是通过InstantiationAwareBeanPostProcessor.postProcessProperties()实现。@Autowired、@Resource、@Value注解都是通过实现了InstantiationAwareBeanPostProcessor接口来处理的。
   7. 依赖注入完后就是初始化操作,分为四步:

7.1 Aware回调,如果bean实现了Aware或其子接口,则会进行Aware的回调。

7.1 初始化前,同初始化后一样是通过BeanPostProcessor机制实现的。

7.2. 初始化,这里如果bean实现了InitializingBean接口,则会调用它的afterPropertiesSet()方法

7.3. 初始化后

8.  销毁方法,在初始化后还有最后一步,就是收集bean的销毁方法信息,将其加入disposableBeans中(一个LinkedHashMap)

1. 当前Bean是否实现了DisposableBean接口
2. 或者,当前Bean是否实现了AutoCloseable接口
3. BeanDefinition中是否指定了destroyMethod
4. 调用DestructionAwareBeanPostProcessor.requiresDestruction(bean)进行判断
    i. ApplicationListenerDetector中直接使得ApplicationListener是DisposableBean
   ii. InitDestroyAnnotationBeanPostProcessor中使得拥有@PreDestroy注解了的方法就是
DisposableBean
5. 把符合上述任意一个条件的Bean适配成DisposableBeanAdapter对象,并存入
disposableBeans中(一个LinkedHashMap)
在Spring容器关闭过程时:
1. 首先发布ContextClosedEvent事件
2. 调用lifecycleProcessor的onCloese()方法
3. 销毁单例Bean
   i. 遍历disposableBeans
    a. 把每个disposableBean从单例池中移除
    b. 调用disposableBean的destroy()
    c. 如果这个disposableBean还被其他Bean依赖了,那么也得销毁其他Bean
    d. 如果这个disposableBean还包含了inner beans,将这些Bean从单例池中移除掉
(inner bean参考https://docs.spring.io/spring-framework/docs/current/spring-
framework-reference/core.html#beans-inner-beans)
   ii. 清空manualSingletonNames,是一个Set,存的是用户手动注册的单例Bean的beanName

getBean方法源码相关推荐

  1. 简单介绍Vue之vue.$set()方法源码案例

    这篇文章主要介绍了Vue之vue.$set()方法源码案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下 在使用vue开发项目的过程中,经常会遇到这样 ...

  2. Transformers包tokenizer.encode()方法源码阅读笔记

    Transformers包tokenizer.encode()方法源码阅读笔记_天才小呵呵的博客-CSDN博客_tokenizer.encode

  3. 【错误记录】Android Studio 中查看 Gradle 配置的方法源码 ( 配置 gradle-wrapper.properties 中版本为 gradle-x.x.x-all.zip )

    文章目录 一.报错信息 二.解决方案 Android Plugin DSL Reference 参考文档 : https://google.github.io/android-gradle-dsl/2 ...

  4. 【Android 异步操作】线程池 ( 线程池 execute 方法源码解析 )

    文章目录 一.线程池 execute 方法源码解析 二.线程池 execute 方法完整源码及注释 一.线程池 execute 方法源码解析 进入 ThreadPoolExecutor 中 , 查看线 ...

  5. 中文分词算法python_Python FMM算法的中文分词器实现方法源码

    这是一篇基于Python代码使用FMM算法达到中文分词效果实现方法的文章.中文语句分词因为编码的关系在Python语言中并不是很好处理,关于中文乱码与编码的问题解决方法,可以参考玩蛇网的Python中 ...

  6. 深入java并发包源码(三)AQS独占方法源码分析

    深入java并发包源码(一)简介 深入java并发包源码(二)AQS的介绍与使用 深入java并发包源码(三)AQS独占方法源码分析 AQS 的实现原理 学完用 AQS 自定义一个锁以后,我们可以来看 ...

  7. erlang下lists模块sort(排序)方法源码解析(二)

    上接erlang下lists模块sort(排序)方法源码解析(一),到目前为止,list列表已经被分割成N个列表,而且每个列表的元素是有序的(从大到小) 下面我们重点来看看mergel和rmergel ...

  8. c#equals方法源码_C#中的Int32.Equals()方法示例

    c#equals方法源码 Int32.Equals()方法 (Int32.Equals() Method) This method is used to compare two integer obj ...

  9. php的setinc方法,thinkphp3.2.0 setInc方法 源码全面解析

    搜索热词 我们先来看一下setInc的官方示例: 需要一个字段和一个自增的值(默认为1) 我们通过下面这个例子来一步步分析他的底层是怎么实现的: class TestController extend ...

最新文章

  1. 给table里面的添加图标_刺激!微信“变色”了!换个带quot;色quot;的图标吧
  2. dubbo源码解析-集群容错架构设计
  3. Silverlight Tips(1)
  4. 怎么将arcgis新建工具条如何保存_ArcGIS中寻找最短路径的方法
  5. 数据结构与算法 --- js描述集合
  6. php的create_function、function_exists判断函数是否存在
  7. python中如何将字典直接变成二维数组_python基础知识(列表、字典、二维数组)...
  8. 安装与优化   98
  9. redis集群如何解决重启不了的问题
  10. linux git 搭建 debian,基于Debian Linux搭建Git服务器
  11. mybatis plus使用in查询
  12. 移动平台前端开发总结(针对iphone,Android等手机)
  13. 基于PyTorch+YOLOv4的口罩佩戴检测,附数据集
  14. php5.3 本地调试,WIN7下PHP 5.3.27和PHPStorm6调试
  15. 剑指offer :跳台阶
  16. Unlocker使用
  17. 中端存储如何摆脱“创新的窘境”
  18. el-table 样式自定义
  19. springmvc+mybatis环境搭建遇到的错误
  20. 企业上云计划:上云前应该考虑哪些因素

热门文章

  1. 计算机绘图在实际工作中的应用,计算机技术在图形图像设计中的应用
  2. 游程理论提取灾害事件特征---基于MATLAB语言的编程实现
  3. 单片机综合实验 - 03 | 音乐门铃设计
  4. 预约服务类APP都有哪些功能
  5. dp (四) 打家劫舍
  6. Java对接阿里云号码隐私保护
  7. Python输入与输出(基础篇)
  8. Deep Q Learning伪代码分析及翻译
  9. spring进行mock测试
  10. [www.miibeian.gov.cn] Alexa综合排名