先看一下调用图,方便后面看代码

@Test
public void testGetBean() {// 业务代码ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-bean.xml");XXXX xxxx = applicationContext.getBean(XXXX.class);
}

org.springframework.context.support.AbstractApplicationContext 

public <T> T getBean(Class<T> requiredType) throws BeansException {assertBeanFactoryActive();return getBeanFactory().getBean(requiredType);
}

org.springframework.beans.factory.support.DefaultListableBeanFactory

@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {return getBean(requiredType, (Object[]) null);
}@Override
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {// 在这一步就把bean获取到了,bean是封装在namedBean中NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);if (namedBean != null) {return namedBean.getBeanInstance();}// 如果当前BeanFactory获取不到,则到父BeanFactory获取BeanFactory parent = getParentBeanFactory();if (parent != null) {return parent.getBean(requiredType, args);}throw new NoSuchBeanDefinitionException(requiredType);
}private <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType, Object... args) throws BeansException {Assert.notNull(requiredType, "Required type must not be null");// 从名称映射缓存Map中取请求名称数组String[] candidateNames = getBeanNamesForType(requiredType);if (candidateNames.length > 1) {List<String> autowireCandidates = new ArrayList<String>(candidateNames.length);for (String beanName : candidateNames) {// isAutowireCandidate该bean是否有资格自动注入if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {autowireCandidates.add(beanName);}}if (!autowireCandidates.isEmpty()) {candidateNames = StringUtils.toStringArray(autowireCandidates);}}if (candidateNames.length == 1) {String beanName = candidateNames[0];// 正常情况,通过getBean获取Bean,有点隐蔽★★★★★// 需要注意的是bean要封装成NamedBeanHolder的形式返回★★★★★return new NamedBeanHolder<T>(beanName, getBean(beanName, requiredType, args));}else if (candidateNames.length > 1) {// 如果有多个的话,根据bean的配置是否有@Primary注解来确定查哪个bean// 加入都有@Primary注解就报错,逻辑在方法:determinePrimaryCandidateMap<String, Object> candidates = new LinkedHashMap<String, Object>(candidateNames.length);for (String beanName : candidateNames) {if (containsSingleton(beanName)) {candidates.put(beanName, getBean(beanName, requiredType, args));}else {candidates.put(beanName, getType(beanName));}}// 决定到底查哪个bean,看bena的@Primary注解String candidateName = determinePrimaryCandidate(candidates, requiredType);if (candidateName == null) {candidateName = determineHighestPriorityCandidate(candidates, requiredType);}if (candidateName != null) {Object beanInstance = candidates.get(candidateName);if (beanInstance instanceof Class) {beanInstance = getBean(candidateName, requiredType, args);}return new NamedBeanHolder<T>(candidateName, (T) beanInstance);}throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());}return null;
}

org.springframework.beans.factory.support.AbstractBeanFactory

public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {// 调用后续方法return doGetBean(name, requiredType, args, false);
}protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException {// 首先对bean name做转换,因为有可能传的是别名final String beanName = transformedBeanName(name);// 定义待返回的bean引用Object bean; // Eagerly check singleton cache for manually registered singletons.// 核心代码:获取单例beanObject sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {if (logger.isDebugEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.debug("Returning cached instance of singleton bean '" + beanName + "'");}}// 这里涉及父子bean的属性合并等,可以过bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {// 代码省略。。。}// Check if required type matches the type of the actual bean instance.if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {try {return getTypeConverter().convertIfNecessary(bean, requiredType);}catch (TypeMismatchException ex) {if (logger.isDebugEnabled()) {logger.debug("Failed to convert bean '" + name + "' to required type '" +ClassUtils.getQualifiedName(requiredType) + "'", ex);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}return (T) bean;
}

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry

@Override
public Object getSingleton(String beanName) {return getSingleton(beanName, true);
}protected Object getSingleton(String beanName, boolean allowEarlyReference) {// 从这里可以看到spring初始化完成以后单例bean的存储位置:singletonObjectsObject singletonObject = this.singletonObjects.get(beanName);// 如果singletonObjects中没有&&当前bean正在创建,进入二三缓存中取// spring在装配bean的时候设置了三级缓存,分别是:// 一级缓存:singletonObjects// 二级缓存:earlySingletonObjects// 三级缓存:singletonFactoriesif (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

Spring源码分析之——getBean细节相关推荐

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

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

  2. Spring源码分析八:Mybatis ORM映射框架原理

    文章目录 (一)Mybatis单独操作数据库程序 1.1.数据库表 1.2.建立PO 1.3.建立mapper接口映射 1.4.建立Mybatis配置文件 1.5.建立mapper映射文件 1.6.测 ...

  3. 【Spring源码分析】Bean加载流程概览

    代码入口 之前写文章都会啰啰嗦嗦一大堆再开始,进入[Spring源码分析]这个板块就直接切入正题了. 很多朋友可能想看Spring源码,但是不知道应当如何入手去看,这个可以理解:Java开发者通常从事 ...

  4. beaninfo详解源码解析 java_【Spring源码分析】Bean加载流程概览

    代码入口 之前写文章都会啰啰嗦嗦一大堆再开始,进入[Spring源码分析]这个板块就直接切入正题了. 很多朋友可能想看Spring源码,但是不知道应当如何入手去看,这个可以理解:Java开发者通常从事 ...

  5. Spring源码分析系列——bean创建过程分析(三)——工厂方法创建bean

    前言 spring创建bean的方式 测试代码准备 createBeanInstance()方法分析 instantiateUsingFactoryMethod()方法分析 总结 spring创建be ...

  6. 手撸spring源码分析IOC实现原理

    手撸spring源码分析IOC实现原理 文章出处:https://github.com/fuzhengwei/small-spring 根据小付哥的手撸spring核心源码一步步学习出来的结果收货总结 ...

  7. spring源码分析之BeanDefinition相关

    目录 前言: BeanDefinition的家族系列 1.BeanDefintion的UML类图 2.BeanDefintion家族类详解 2.1.通用接口 2.2.BeanDefintion接口 2 ...

  8. Spring源码分析(三)

    Spring源码分析 第三章 手写Ioc和Aop 文章目录 Spring源码分析 前言 一.模拟业务场景 (一) 功能介绍 (二) 关键功能代码 (三) 问题分析 二.使用ioc和aop重构 (一) ...

  9. Spring源码分析之Bean的创建过程详解

    前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...

最新文章

  1. python导入excel数据-Python数据处理之导入导出excel数据
  2. 海贼王热血航线正在连接服务器,航海王热血航线连接服务器失败?解决方法一览...
  3. 多功能视频光端机_多业务光端机的功能特性
  4. 【Java】异常处理的目的
  5. nodejs 调用微服务器_无服务器NodeJS:构建下一个微服务的快速,廉价方法
  6. STL map与Boost unordered_map - 有何不可的日志 - 网易博客
  7. ccf小明放学20分_关于完全平方数的好题(20年3月1日)
  8. 实习也能这样过!节选
  9. CSS中怎么让DIV水平居中
  10. Cdence版图设计手册
  11. 创业维艰-公司业务解决方案推荐!
  12. itextpdf 给pdf文档添加图片
  13. 第4版 网页设计与制作 HTML5+CSS3+JavaScript(赵丰年 编著)学习笔记
  14. 大厂面试:一个四年多经验程序员的BAT面经(字节、阿里、腾讯)
  15. bootmgr快速修复win7_Win7进入死亡倒计时,全国一半电脑要遭殃?
  16. (J3455/J3155/J4015/J4105/……)无线网卡M.2(ngff) keyA/E接口扩展sata硬盘接口,黑群辉NAS系统
  17. 苹果为开发人员播种macOS Big Sur 11.3的第七个Beta
  18. Photoshop基础教程
  19. android usb麦克风阵列,语音设备 SDK 麦克风阵列建议
  20. PostgreSQL 14分布式Citus单机多实例部署

热门文章

  1. 设计模式之原型模式与深浅拷贝
  2. 信息流的html落地页怎么制作,信息流广告落地页如何做?-鱼爪网
  3. 深度学习——残差网络(ResNet)
  4. android编译出来的内核是dtb,内核编译出现错误,求大神教
  5. 华为运营商级路由器配置示例 | 配置OptionC方式跨域BGP VPLS示例
  6. 以太网交换机的自学习
  7. 西奥服务器修改楼层参数,杭州西奥OHCON8503电梯LMCB板楼层表(井道)自学习
  8. ROS-CAN通信解析程序分析(ROS中进行CAN通信)
  9. xadmin的安装及配置
  10. 使用class-dump-z