getBean 方法是用来进行获取 bean 实例对象的,是我们进行 spring 程序开发从 bean 工厂获取结果的。那这个方法的执行过程是什么样的,下面我们就去揭开它的面纱。

样例代码

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = ctx.getBean("user", User.class);

getBean 方法执行过程

  1. org.springframework.context.support.AbstractApplicationContext.getBean(String, Class)
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {// 判断 bean 工厂是否处于激活状态// 对于 ClassPathXmlApplicationContext 实例此方法默认实现是空的assertBeanFactoryActive();return getBeanFactory().getBean(name, requiredType);
}
  1. org.springframework.context.support.AbstractRefreshableApplicationContext.getBeanFactory()
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {DefaultListableBeanFactory beanFactory = this.beanFactory;if (beanFactory == null) {throw new IllegalStateException("BeanFactory not initialized or already closed - " +"call 'refresh' before accessing beans via the ApplicationContext");}return beanFactory;
}
  1. org.springframework.beans.factory.support.AbstractBeanFactory.getBean(String, Class)
@Overridepublic <T> T getBean(String name, Class<T> requiredType) throws BeansException {return doGetBean(name, requiredType, null, false);}
  1. org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(String, Class, Object[], boolean)
@SuppressWarnings("unchecked")
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType,@Nullable Object[] args, boolean typeCheckOnly) throws BeansException {// bean 名称处理:去除工厂引用前缀,规范别名规则String beanName = transformedBeanName(name);Object bean;// 首先,从单例缓存中获取 beanName 对应的 bean 实例// 如果单例缓存中没有则会新建.Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {if (logger.isTraceEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");} else {logger.trace("Returning cached instance of singleton bean '" + beanName + "'");}}// 注入该实例需要依赖的 bean bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);} else {// Fail if we're already creating this bean instance:// We're assumably within a circular reference.if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.String nameToLookup = originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);} else if (args != null) {// Delegation to parent with explicit args.return (T) parentBeanFactory.getBean(nameToLookup, args);} else if (requiredType != null) {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);} else {return (T) parentBeanFactory.getBean(nameToLookup);}}if (!typeCheckOnly) {markBeanAsCreated(beanName);}try {RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);// Guarantee initialization of beans that the current bean depends on.String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {for (String dep : dependsOn) {if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}registerDependentBean(dep, beanName);try {getBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}// Create bean instance.if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It might have been put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}else if (mbd.isPrototype()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}else {String scopeName = mbd.getScope();if (!StringUtils.hasLength(scopeName)) {throw new IllegalStateException("No scope name defined for bean 麓" + beanName + "'");}Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {Object scopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}});bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {throw new BeanCreationException(beanName,"Scope '" + scopeName + "' is not active for the current thread; consider " +"defining a scoped proxy for this bean if you intend to refer to it from a singleton",ex);}}}catch (BeansException ex) {cleanupAfterBeanCreationFailure(beanName);throw ex;}}// 检查 bean 实例类型是否与指定的类型相匹配.if (requiredType != null && !requiredType.isInstance(bean)) {try {T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);if (convertedBean == null) {throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}return convertedBean;} catch (TypeMismatchException ex) {if (logger.isTraceEnabled()) {logger.trace("Failed to convert bean '" + name + "' to required type '" +ClassUtils.getQualifiedName(requiredType) + "'", ex);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}return (T) bean;
}

至此 getBean 方法的执行过程已讲解完毕。可能大家注意到 doGetBean 部分代码没有讲解到,这是由于咱们的示例代码在执行的过程中没有执行到这部分的代码,所以没有给大家讲解,后续如果样例程序中涉及到这部分代码,我会详细讲解的。读过 spring 源码的朋友都知道,spring 的架构非常好,考虑非常周全,而且扩展性特别强,这是值得我们学习和借鉴的。

Spring源码讲解之 getBean 方法相关推荐

  1. Spring源码分析之getBean主流程分析

    当我们通过向Spring容器获取某个bean的时候,总是调用Spring中重载的各种getBean方法.那么,getBean中的流程是什么样的? 通过本文,你将对getBean方法的主流程有一个详细的 ...

  2. Spring源码之BeanFactory.getBean()

    本文是针对Srping的BeanFactory.getBean来进行源码解析,如果您是第一次看请先看一下XMLBeanFactory解析:https://blog.csdn.net/qq_302571 ...

  3. Spring源码解析之getBean(beanName)

    获取Spring Bean大体步骤: 调用BeanDefinitionReader的loadBeanDefinitions()方法解析并加载bean配置信息,转换位BeanDefinition对象 讲 ...

  4. Spring源码分析之——getBean细节

    先看一下调用图,方便后面看代码 @Test public void testGetBean() {// 业务代码ApplicationContext applicationContext = new ...

  5. Spring 源码讲解:bean 的创建流程 - 公开课笔记

    Spring 官网所有版本下载 官网文档中的链接找起来比较麻烦.我们可以通过下面这个链接: https://repo.spring.io/release/org/springframework/spr ...

  6. Spring源码深度解析(郝佳)-学习-Spring消息-整合RabbitMQ及源码解析

      我们经常在Spring项目中或者Spring Boot项目中使用RabbitMQ,一般使用的时候,己经由前人将配置配置好了,我们只需要写一个注解或者调用一个消息发送或者接收消息的监听器即可,但是底 ...

  7. Spring源码分析-深入理解生命周期之BeanFactoryProcessor

    生命周期之BeanFactoryPostProcessor 先来看看bean的生命周期.对于熟悉spring 的朋友来说,bean的生命周期并不陌生.它可以在bean加载,bean初始化的过程中加入我 ...

  8. Spring源码分析系列-Bean的生命周期(总结篇)

    ApplicationContext和BeanFactory   BeanFactory是Spring中的顶层接口,只负责管理bean,而ApplicationContext也实现了BeanFacto ...

  9. Spring源码之getBean(获取 bean)方法(二)解读

    目录 前言 `spring` 初始化 `bean` 过程 进入类 `ClassPathXmlApplicationContext` 的构造器 `AbstractApplicationContext` ...

最新文章

  1. linux tomcat端口冲突解决
  2. 2021-08-04 jpg和png批量转化8位到24位,相互转化!
  3. EasyTouch初步使用
  4. wp7上MD5加密类
  5. mysql查询根据季度查询_Mysql 按年、季度、月查询统计
  6. 框架 路由地址_Django框架的使用
  7. Linux指纹识别相关配置
  8. 28部漫威电影按漫威时间全梳理
  9. html设置尖角,CSS为div添加尖角样式
  10. 鱼香肉丝里到底有没有鱼?
  11. Unreal Engine 4(虚幻UE4)GameplayAbilities 插件入门教程(三)技能标签(Ability Tags)
  12. 春考计算机组装维修知识点,山东春考计算机组装及维修模拟题.docx
  13. STM32/CPU总线的由来和地址映射概念
  14. 杭电2019多校第三场 HDU-6608 Fansblog
  15. 国内电子商务网站分析报告
  16. 做国外LEAD需要一些邮箱怎么办
  17. 长春初一学生数学补习班哪家好/麦田1对1补习费用
  18. migo初始化库存 s4_【S4 MM】S4中继续使用MB系统事务代码
  19. 纯 CSS3 实现漂亮的 input 输入框
  20. Linux配置校时服务器

热门文章

  1. 杂谈:淘宝商城“”事件
  2. 至强E5-2600v4系列CPU一览表
  3. Android进阶——组件化开发实践(一)
  4. 热爱生活,热爱学习!
  5. java version 7 下载_JDK 7u60 版本发布下载安装
  6. Ubuntu 80端口无法使用-非root用户无法使用1024以下端口
  7. uni-app时间戳转换日期格式
  8. 维也纳春之声交响乐团新年音乐会 观赏感想
  9. 官宣!这款网红产品低代码平台可以终身免费使用!!!
  10. 海贼王热血航线服务器维护,航海王热血航线手游2021年3月23日例行停服维护公告_航海王热血航线手游3月23日更新了什么_玩游戏网...