解析BeanFactory的核心方法——getBean
本系列源码都是基于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相关推荐
- Java Executor源码解析(3)—ThreadPoolExecutor线程池execute核心方法源码【一万字】
基于JDK1.8详细介绍了ThreadPoolExecutor线程池的execute方法源码! 上一篇文章中,我们介绍了:Java Executor源码解析(2)-ThreadPoolExecutor ...
- spring源码解析之IOC核心体系结构
文章目录 1.spring IOC核心体系结构 1.1 BeanFactory 1.2 BeanDefinition 2.IOC容器初始化 2.1 XmlBeanFactory(屌丝IOC)流程 2. ...
- Spring 核心方法 refresh 刷新流程简要概述及相关源码扩展实现(一)
前言 Spring 启动流程解析 Refresh 内部方法全解析 prepareRefresh obtainFreshBeanFactory AbstractApplicationContext 类以 ...
- Spring 核心方法 refresh 刷新流程简要概述及相关源码扩展实现(二)
前言 registerBeanPostProcessors initMessageSource 如何实际应用国际化处理 initApplicationEventMulticaster onRefres ...
- spring源码依赖注入的核心方法populateBean(beanName, mbd, instanceWrapper)分析
spring源码依赖注入的核心方法populateBean(beanName, mbd, instanceWrapper)分析:通过源码我们发现在分析这个方法之前,此对象已经创建完成实例,内存开辟了空 ...
- Spring Cloud Gateway-ServerWebExchange核心方法与请求或者响应内容的修改
Spring Cloud Gateway-ServerWebExchange核心方法与请求或者响应内容的修改 前提 本文编写的时候使用的Spring Cloud Gateway版本为当时最新的版本Gr ...
- jQuery方法源码解析--jQuery($)方法(一)
jQuery方法源码解析--jQuery($)方法 注: 1.本文分析的代码为jQuery.1.11.1版本,在官网上下载未压缩版即可 2.转载请注明出处 jQuery方法: 这个方法大家都不陌生,在 ...
- 2020-08-24绘制ROC PR曲线 核心方法总结 ,计算AUC核心方法
#1 绘制ROC AUC PR曲线 #核心方法 roc_curve(y_test, preds) # preds为概率形式 #source code import matplotlib.p ...
- 王者荣耀s22服务器未响应是什么意思,王者荣耀s22资源包升级失败 s22解析包出现问题解决方法...
王者荣耀s22资源包升级失败怎么解决?相信大家都知道王者荣耀S22破晓版本在今日14日正式推出,一时间大量玩家去更新游戏,不过有一小部分玩家出现了更新问题,那就是资源包升级错误,关于这个问题,官方也给 ...
最新文章
- 量子计算,后摩尔时代计算能力提升的解决方案
- Oracle rac进阶管理专家指导系列文档
- cmd 顺序启动服务_window下启动redis步骤和服务报错解决办法
- [html] 说说html5手势检测原理是什么?
- SAGAN(G-lab介绍)
- 一键安装zabbix监控redis
- JavaScript之BOM基础
- Android 心跳呼吸动画
- 红帽Linux故障定位技术详解与实例(3)
- for range循环通道
- php 滑块 爬虫_PHP实现简易爬虫与简易采集程序
- mysql如何开启对外连接?
- Markdown中的特殊符号
- 2008生产实习 日程安排
- Flex里[Exclude]标签的作用:对外忽略/隐藏内部某对象
- 挑战程序设计竞赛:Conscription
- ADS软件仿真的问题
- java new thread名字_Java的每个Thread都希望拥有自己的名称
- 小游戏《俄罗斯方块》开发
- 格斗机器人制造图纸_一种新型格斗机器人的制作方法