本系列源码都是基于spring-4.3.8版本之上,其他版本略有差异,但总体的核心思想相同。同时,为了使贴出的源代码尽可能的紧凑,可能会删去一些异常捕获、日志输出等代码。若文中存在纰漏错误,欢迎指正。

先看一下BeanFactory中定义的所有getBean方法

    Object getBean(String name) throws BeansException;<T> T getBean(String name, Class<T> requiredType) throws BeansException;<T> T getBean(Class<T> requiredType) throws BeansException;Object getBean(String name, Object... args) throws BeansException;<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

以上五个getBean方法中,所有带beanName参数的方法都在AbstractBeanFactory中实现了,其余的两个也在DefaultListableBeanFactory中实现了。

AbstractBeanFactory中的getBean

    @Overridepublic Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);}@Overridepublic <T> T getBean(String name, Class<T> requiredType) throws BeansException {return doGetBean(name, requiredType, null, false);}@Overridepublic Object getBean(String name, Object... args) throws BeansException {return doGetBean(name, null, args, false);}public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {return doGetBean(name, requiredType, args, false);}

DefaultListableBeanFactory中的getBean

    @Overridepublic <T> T getBean(Class<T> requiredType) throws BeansException {return getBean(requiredType, (Object[]) null);}@Overridepublic <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);if (namedBean != null) {return namedBean.getBeanInstance();}BeanFactory parent = getParentBeanFactory();if (parent != null) {return parent.getBean(requiredType, args);}throw new NoSuchBeanDefinitionException(requiredType);}

可以看出除了DefaultListableBeanFactory#getBean(Class<T> requiredType, Object... args)之外,其他的方法都是通过直接通过AbstractBeanFactory#doGetBean获取bean的。

那么我们再重新看一下这个看似不同的getBean方法

    public <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException {// 调用当前类的resolveNamedBean获取NamedBeanHolderNamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, (Object[]) null);if (namedBean != null) {return namedBean;}// 若获取不到,则获取parentBeanFactory,以parentBeanFactory#resolveNamedBean获取NamedBeanHolderBeanFactory parent = getParentBeanFactory();if (parent instanceof AutowireCapableBeanFactory) {return ((AutowireCapableBeanFactory) parent).resolveNamedBean(requiredType);}throw new NoSuchBeanDefinitionException(requiredType);}

看来关键还是得看DefaultListableBeanFactory#resolveNamedBean

    @SuppressWarnings("unchecked")private <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType, Object... args) throws BeansException {Assert.notNull(requiredType, "Required type must not be null");// 以beanClass换取beanName,即通过该bean的类型从allBeanNamesByType中获取beanName// 候选者beanName数组String[] candidateNames = getBeanNamesForType(requiredType);if (candidateNames.length > 1) {List<String> autowireCandidates = new ArrayList<String>(candidateNames.length);// 通过beanName获取BeanDefinition,且BeanDefinition#autowireCandidate为true即可加入候选组,该值默认即truefor (String beanName : candidateNames) {if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {autowireCandidates.add(beanName);}}// 将经过筛选的候选者重新赋值到candidateNamesif (!autowireCandidates.isEmpty()) {candidateNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);}}// 候选者若只有一个,那直接以该beanName通过AbstractBeanFactory#getBean获取bean实例if (candidateNames.length == 1) {String beanName = candidateNames[0];// 依然是以beanName从AbstractBeanFactory#getBean获取bean实例return new NamedBeanHolder<T>(beanName, getBean(beanName, requiredType, args));}// 若候选者不止一个,则需要重新选举最合适的else if (candidateNames.length > 1) {Map<String, Object> candidates = new LinkedHashMap<String, Object>(candidateNames.length);for (String beanName : candidateNames) {if (containsSingleton(beanName)) {// 依然是以beanName从AbstractBeanFactory#getBean获取bean实例candidates.put(beanName, getBean(beanName, requiredType, args));} else {candidates.put(beanName, getType(beanName));}}// 首先通过AbstractBeanDefinition#primary筛选候选者String candidateName = determinePrimaryCandidate(candidates, requiredType);if (candidateName == null) {// 若筛选失败,候选者都被淘汰时,再重新以Priority进行筛选候选者candidateName = determineHighestPriorityCandidate(candidates, requiredType);}if (candidateName != null) {Object beanInstance = candidates.get(candidateName);if (beanInstance instanceof Class) {// 依然是以beanName从AbstractBeanFactory#getBean获取bean实例beanInstance = getBean(candidateName, requiredType, args);}return new NamedBeanHolder<T>(candidateName, (T) beanInstance);}throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());}return null;}

可以看出,该方法除了最后的返回null和抛出异常结束之外,其余的出口也依然是通过AbstractBeanFactory#getBean获取实例的,所以绕了半天,其本质依然是通过AbstractBeanFactory#doGetBean获取bean实例的。

因此所有的getBean只是通过不同的传参方式调用doGetBean,其本质上还是得通过AbstractBeanFactory#doGetBean获取bean实例的,所以看来重点就是这个doGetBean方法了。

    /*** {@link AbstractBeanFactory#getBean(String)}* {@link AbstractBeanFactory#getBean(String, Class)}* {@link AbstractBeanFactory#getBean(String, Object...)}* {@link AbstractBeanFactory#getBean(String, Class, Object...)}* {@link DefaultListableBeanFactory#getBean(Class)}* {@link DefaultListableBeanFactory#getBean(Class, Object...)}* AbstractBeanFactory中实现了大部分的getBean,剩余的在DefaultListableBeanFactory中实现* 而不论哪一种最终都是需要通过doGetBean获取bean实例*/@SuppressWarnings("unchecked")protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args,boolean typeCheckOnly) throws BeansException {/*** 对name进行解析,主要做了两件事:* (1)将name开头的所有"&"去除,并赋值给beanName,如此一来,name负责处理与factoryBean有关的bean获取,* 而beanName则用来获取所有其他bean。* (2)以转换后的name调用SimpleAliasRegistry.canonicalName(String),以alias别名换取id*/final String beanName = transformedBeanName(name);Object bean;/*** 尝试以singleton的方式调用DefaultSingletonBeanRegistry.getSingleton(String)获取bean,* 这个方法还会以allowEarlyReference=true即允许早期引用的形式继续调用getSingleton(String beanName,* boolean allowEarlyReference)。* 该方法会先从一级缓存singletonObjects以及二级缓存earlySingletonObjects中获取,* 若依然获取不到,由于allowEarlyReference=true,则会继续从三级缓存singletonFactories中获取objectFactorys,* 若获取到了就以objectFactory#getObject的方式获取bean。 执行过程可能是以下的几种情况:* 1、从一级缓存singletonObjects中获取bean,若获取到了说明获取的bean早就被创建好了,否则继续获取* 2、一级缓存未获取到,继续从二级缓存earlySingletonObjects中获取,若获取到了,说明该beanName虽然已被创建完毕,* 但还非完全实例化完毕(singletonsCurrentlyInCreation中必然存在该beanName),* 只是提早暴露了出来而已。(而之所以会在二级缓存earlySingletonObjects中,请看(3))* 3、一级、二级缓存中都未获取到,且allowEarlyReference=true的时候,从三级缓存singletonFactories中获取,* 获取到的是objectFactory,若获取到了,说明当前beanName正在创建中,尚未完全创建完毕,* 只是提前将自己的制造工厂——ObjectFactory暴露出来了而已,然后继续调用ObjectFactory#getObject获取bean,* 一般而言,这里的ObjectFactory#getObject都是在AbstractAutowireCapableBeanFactory.doCreateBean中添加的,* 且getObject方法是调用AbstractAutowireCapableBeanFactory.getEarlyBeanReference获取早期引用的。* 4、三级缓存中也没有获取到,说明当前bean尚未被加载过,方法执行完毕,doGetBean继续向下执行。*/Object sharedInstance = getSingleton(beanName);/*** 根据之前的getSingleton(String)是否从缓存中获取到了bean决定如何执行:* 1、若获取到了,则继续调用AbstractBeanFactory.getObjectForBeanInstance判断该类是否实现了FactoryBean,* 若实现了则调用getObject获取bean,否则依然返回bean。 2、若未获取到则说明该bean尚未被初始化或者其根本就不是单例而是多例,继续执行下去*/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 = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// 尝试获取父容器,并从父容器中获取beanBeanFactory parentBeanFactory = getParentBeanFactory();// 若父容器存在,且当前容器不包含该beanName,则尝试从父容器获取beanif (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// 转化beanName,去除"&",并以alias别名换取idString nameToLookup = originalBeanName(name);// 从父容器获取beanif (args != null) {// Delegation to parent with explicit args.return (T) parentBeanFactory.getBean(nameToLookup, args);} else {return parentBeanFactory.getBean(nameToLookup, requiredType);}}/*** 用来标记当前bean是否已被创建完毕的方法,若当前bean尚未被创建,则执行完该方法,* 其就会被加入到AbstractBeanFactory.alreadyCreated中,表示该bean已被创建或即将被创建。* 根据doGetBean的第三个参数markBeanAsCreated决定是否执行该方法,* 目前的所有getBean方法都默认会将typeCheckOnly设置为false,即都会执行该方法。*/if (!typeCheckOnly) {markBeanAsCreated(beanName);}try {/*** 获取合并后的本地BeanDefinition,* 根据beanName从AbstractBeanFactory#mergedBeanDefinitions中获取RootBeanDefinition,* 若获取不到,则调用DefaultListableBeanFactory.getBeanDefinition,从beanDefinitionMap中获取BeanDefinition,* 获取不到就抛出NoSuchBeanDefinitionException,* 否则就继续调用AbstractBeanFactory.getMergedBeanDefinition(String, BeanDefinition)*/final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);/*** 获取该bean的依赖,若存在,则逐个以DefaultSingletonBeanRegistry.registerDependentBean添加到dependentBeanMap中* 并通过AbstractBeanFactory.getBean(String)保证当前Bean依赖的Bean全部被初始化,所以递归getBean。*/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);getBean(dep);}}/*** 若是单例,则调用DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory<?>),* 同时通过内部类的方式重写了ObjectFactory#getObject,* 其会先从缓存DefaultSingletonBeanRegistry#singletonObjects中获取,* 获取不到则说明该bean还未被实例化,以ObjectFactory#getObject继续获取该bean实例,* 然后以匿名内部类的方式调用AbstractBeanFactory#createBean进行创建bean的操作,* 实例化完成后,调用DefaultSingletonBeanRegistry#addSingleton将其放入缓存map-singletonObjects中,* 这样之后调用就不会再创建了*/if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {@Overridepublic Object getObject() throws BeansException {try {return createBean(beanName, mbd, args);} catch (BeansException ex) {destroySingleton(beanName);throw ex;}}});// 判断是否需要继续转化为FactoryBean获取beanbean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}// 若是多例,则会直接调用上述AbstractBeanFactory#createBean直接创建bean。else if (mbd.isPrototype()) {Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);} finally {afterPrototypeCreation(beanName);}// 判断是否需要继续转化为FactoryBean获取beanbean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}/*** 若均不是,则调用AbstractBeanDefinition.getScope()获取该bean的Scope,* 而后重写Scope#getObject并调用Scope.get(String, ObjectFactory<?>)获取bean实例,* 最终依然会调用刚才重写的getObject并调用createBean创建bean。*/else {String scopeName = mbd.getScope();final 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, new ObjectFactory<Object>() {@Overridepublic Object getObject() throws BeansException {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);} finally {afterPrototypeCreation(beanName);}}});// 判断是否需要继续转化为FactoryBean获取beanbean = 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,但是bean类型又与期待的类型不匹配时,调用TypeConverter#convertIfNecessary进行类型转换if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {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;}

解析BeanFactory的核心方法——getBean相关推荐

  1. Java Executor源码解析(3)—ThreadPoolExecutor线程池execute核心方法源码【一万字】

    基于JDK1.8详细介绍了ThreadPoolExecutor线程池的execute方法源码! 上一篇文章中,我们介绍了:Java Executor源码解析(2)-ThreadPoolExecutor ...

  2. spring源码解析之IOC核心体系结构

    文章目录 1.spring IOC核心体系结构 1.1 BeanFactory 1.2 BeanDefinition 2.IOC容器初始化 2.1 XmlBeanFactory(屌丝IOC)流程 2. ...

  3. Spring 核心方法 refresh 刷新流程简要概述及相关源码扩展实现(一)

    前言 Spring 启动流程解析 Refresh 内部方法全解析 prepareRefresh obtainFreshBeanFactory AbstractApplicationContext 类以 ...

  4. Spring 核心方法 refresh 刷新流程简要概述及相关源码扩展实现(二)

    前言 registerBeanPostProcessors initMessageSource 如何实际应用国际化处理 initApplicationEventMulticaster onRefres ...

  5. spring源码依赖注入的核心方法populateBean(beanName, mbd, instanceWrapper)分析

    spring源码依赖注入的核心方法populateBean(beanName, mbd, instanceWrapper)分析:通过源码我们发现在分析这个方法之前,此对象已经创建完成实例,内存开辟了空 ...

  6. Spring Cloud Gateway-ServerWebExchange核心方法与请求或者响应内容的修改

    Spring Cloud Gateway-ServerWebExchange核心方法与请求或者响应内容的修改 前提 本文编写的时候使用的Spring Cloud Gateway版本为当时最新的版本Gr ...

  7. jQuery方法源码解析--jQuery($)方法(一)

    jQuery方法源码解析--jQuery($)方法 注: 1.本文分析的代码为jQuery.1.11.1版本,在官网上下载未压缩版即可 2.转载请注明出处 jQuery方法: 这个方法大家都不陌生,在 ...

  8. 2020-08-24绘制ROC   PR曲线 核心方法总结 ,计算AUC核心方法

    #1   绘制ROC AUC   PR曲线 #核心方法 roc_curve(y_test, preds)  #  preds为概率形式 #source code import matplotlib.p ...

  9. 王者荣耀s22服务器未响应是什么意思,王者荣耀s22资源包升级失败 s22解析包出现问题解决方法...

    王者荣耀s22资源包升级失败怎么解决?相信大家都知道王者荣耀S22破晓版本在今日14日正式推出,一时间大量玩家去更新游戏,不过有一小部分玩家出现了更新问题,那就是资源包升级错误,关于这个问题,官方也给 ...

最新文章

  1. 量子计算,后摩尔时代计算能力提升的解决方案
  2. Oracle rac进阶管理专家指导系列文档
  3. cmd 顺序启动服务_window下启动redis步骤和服务报错解决办法
  4. [html] 说说html5手势检测原理是什么?
  5. SAGAN(G-lab介绍)
  6. 一键安装zabbix监控redis
  7. JavaScript之BOM基础
  8. Android 心跳呼吸动画
  9. 红帽Linux故障定位技术详解与实例(3)
  10. for range循环通道
  11. php 滑块 爬虫_PHP实现简易爬虫与简易采集程序
  12. mysql如何开启对外连接?
  13. Markdown中的特殊符号
  14. 2008生产实习 日程安排
  15. Flex里[Exclude]标签的作用:对外忽略/隐藏内部某对象
  16. 挑战程序设计竞赛:Conscription
  17. ADS软件仿真的问题
  18. java new thread名字_Java的每个Thread都希望拥有自己的名称
  19. 小游戏《俄罗斯方块》开发
  20. 格斗机器人制造图纸_一种新型格斗机器人的制作方法

热门文章

  1. ffmpeg 后台运行
  2. AE+C#二次开发,矢量数据空间分析——裁剪分析
  3. Python大法之告别脚本小子系列——信息资产收集类脚本编写附源码
  4. Java char-'0'--char转换为int
  5. 内衣店连环营销方案,多方合作让各方都赚钱的神秘方案分享
  6. hide show toggle
  7. 设计模式:简单工厂、工厂、抽象工厂
  8. SSL_2291【分组背包】
  9. 大数据机器学习是什么,主要能应用到哪些领域?
  10. python环境配置和安装