doGetBean方法详解
doGetBean方法:
该方法位于
-> AbstractApplicationContext.refresh()
-> AbstractApplicationContext.finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory)
-> DefaultListableBeanFactory.preInstantiateSingletons()
-> AbstractBeanFactory.getBean(String name)
-> AbstractBeanFactory.doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly)
doGetBean方法大致流程:
doGetBean()方法代码:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { //通过三种形式获取beanName //一个是原始的beanName,一个是加了&的,一个是别名 final String beanName = transformedBeanName(name);//返回容器中真实的BeanName Object bean;//创建bean,该bean最后会被返回 // Eagerly check singleton cache for manually registered singletons. //尝试从单例缓存集合里获取bean实例 Object sharedInstance = getSingleton(beanName);//从一二三级缓存中依次获取 //如果先前已经创建过单例Bean的实例,并且调用的getBean方法传入的参数为空 //则执行if里面的逻辑 //args之所以要求为空是因为如果有args,则需要做进一步赋值,因此无法直接返回 if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { //如果Bean还在创建中,则说明是循环引用 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,直接返回,如果是FactoryBean,则返回它的getObject bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } //若scope为prototype或者单例模式但是缓存中还不存在bean else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. //如果scope为prototype并且 显示还在创建中,则基本是循环依赖的情况 //针对prototype的循环依赖,spring误解,直接抛出异常 // A -> B -> A if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName);//在Spring中是不支持循环依赖的,所以这里会抛出异常 } // Check if bean definition exists in this factory.(检查这个工厂中是否存在bean定义。) BeanFactory parentBeanFactory = getParentBeanFactory();//获取其父容器 //从当前容器中找不到指定名称的bean,此时递归去parentFactory查找 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. //主要针对FactoryBean,将Bean的&重新加上 String nameToLookup = originalBeanName(name);//将转换过后的BeanName恢复回原先的样子 //如果parent容器依旧是AbstractBeanFactory的实例 //instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例 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); } } //typeCheckOnly是用来判断调用getBean()是否仅仅是为了类型检查获取bean,而不是为了创建Bean if (!typeCheckOnly) { //如果不是仅仅做类型检查则是创建bean markBeanAsCreated(beanName);//标记Bean方便创建(清除合并BeanDefinition的标记)使之重新合并 } try { //将父类的BeanDefinition与子类的BeanDefinition进行合并覆盖 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);//合并父子类的BeanDefinition操作 //对合并的BeanDefinition做验证,主要看属性是否为abstract的 checkMergedBeanDefinition(mbd, beanName, args);//查看是否为抽象 // Guarantee initialization of beans that the current bean depends on. //获取当前Bean所有依赖Bean的名称 String[] dependsOn = mbd.getDependsOn();//获取所有依赖的名称 //如果当前Bean设置了dependsOn的属性 //depends-on用来指定Bean初始化及销毁时的顺序 //<bean id="a" Class="com.imooc.A" depends-on="b" /> //<bean id="b" Class="com.imooc.B" /> if (dependsOn != null) { for (String dep : dependsOn) {//遍历所有依赖 //校验该依赖是否已经注册给当前bean,注意这里传入的key是当前的bean名称 //这里主要是判断是否有以下这种类型的依赖: //<bean id="beanA" Class="com.imooc.A" depends-on="beanB" /> //<bean id="beanB" Class="com.imooc.B" depends-on="beanA" /> //如果有,直接抛出异常 if (isDependent(beanName, dep)) { //循环依赖抛异常 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } //缓存依赖调用,注意这里传入的key是被依赖的bean名称 registerDependentBean(dep, beanName); try { //递归调用getBean方法,注册Bean之间的依赖(如C需要晚于B初始化,而B需要晚于A初始化) //初始化依赖的bean getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // Create bean instance. //如果BeanDefinition为单例 if (mbd.isSingleton()) { //这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象 //sharedInstance:共享实例 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. //显示从单例缓存中删除bean实例 //因为单例模式下为了解决循环依赖,可能它已经存在了,所有将其销毁 destroySingleton(beanName); throw ex; } }); //如果是普通bean,直接返回,如果是FactoryBean,则返回它的getObject bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. //Prototype每次都会创建一个新的对象 Object prototypeInstance = null; try { //默认的功能是注册当前创建的prototype对象为正在创建中 beforePrototypeCreation(beanName); //创建原型对象实例 prototypeInstance = createBean(beanName, mbd, args); } finally { //默认的功能是将先前注册的正在创建中的Bean信息给抹除掉 afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } //要创建的Bean既不是单态模式,也不是原型模式,则根据Bean定义资源中 //配置的生命周期范围,选择实例化Bean的合适方法,这种在Web应用程序中 //比较常用,如:request、session、application等生命周期 else { String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); //Bean定义资源中没有配置生命周期范围,则Bean定义不合法 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; } } // Check if required type matches the type of the actual bean instance. //对创建的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;//返回Bean实例 }
代码解析:
1.执行transformedBeanName()方法,该方法将doGetBean的参数name转换成容器中真实的beanName(获取容器中真实beanName)(传递过来的name有三种可能,一个是原始的beanName,一个是加了&的,一个是别名。所以我们要统一将其转换 )
2.getSingleton()方法,该方法将尝试从单例缓存集合里获取bean实例。
(1)尝试从一级缓存里面获取完备的Bean(一级缓存中获取完备的Bean)
(2)if(如果没有在一级缓存中获取到Bean & 正在创建Bean的缓存名单中有该BeanName){
尝试给一级缓存对象加锁,接下来就要对缓存对象操作了
尝试从二级缓存earlySingletonObjects这个存储还没进行属性添加操作的Bean实例缓存中获取(二级缓存中获取还未添加属性的Bean)
if(如果还没有获取到并且第二个参数为true,为true则表示bean允许被循环引用){
从三级缓存singletonFactories这个ObjectFactory实例的缓存里尝试获取创建此Bean的单例工厂实例(三级缓存中获取Bean工厂)
if(如果获取到工厂实例){
调用单例工厂的getObject方法返回对象实例,将实例放入二级缓存里,从三级缓存里移除
}
}
}
(3)返回获取的Bean
3.判断从单例缓存集合里获取的bean实例是否存在且是否有args(参数),最终创建赋值上bean
if代码块
(1)判断其是否有被其他bean引用,随之打印日志
(2)最后调用getObjectForBeanInstance()方法获取赋值bean实例。
getObjectForBeanInstance()方法
(A)校验传递过来的beanName是否为FactoryBean
(B)getCachedObjectForFactoryBean尝试从缓存中获取Factorybean早已创建出的bean实例
(C)如果没有获取到Bean实例,会调用getMergedLocalBeanDefinition()方法根据beanName尝试从容器中对应的BeanDefinition实例
(D)最终调用⭐getObjectFromFactoryBean()方法创建Bean实例(该方法中有涉及第三方框架可以在其中用AOP包装Bean实例,创建单例Bean完成)
else代码块。
(1)判断是否存在循环依赖情况,有则抛出异常 (Spring中不支持循环依赖)
(2)获取父容器
(3)如果容器存在且容器中找不到beanName,则先将BeanName恢复回原先的样子然后递归调用doGetBean()方法重新找一遍
(4)判断调用getBean()是否仅仅是为了类型检查获取bean,如果是为了创建bean,则先清除掉合并BeanDefinition的标记(使之重新合并)
(5)合并父子BeanDefinition //getMergedLocalBeanDefinition():将bd传入合并上pbd(ParentBeanDefinition)返回mbd(MergedBeanDefinition)如果pdb上面还有需要合并的pdb,就递归合并
(6)查看合并后的BeanDefinition是否为抽象(是则抛异常)
(7)获取到BeanDefinition的所有依赖名称(获取所有依赖String[ ])
(8)如果依赖名称数组不为空,则遍历数组,逐个获取依赖。首先判断依赖是否存在循环依赖情况,有则抛异常。第二缓存依赖调用, 第三递归调用getBean方法,注册Bean之间的依赖
(9).判断BeanDefinition的类型(单例,原型,其他)作出相应的创建Bean
单例:
(A)调用getSingleton()方法,参数中传递了一个匿名内部类,该类实现了ObjectFactory类的getObject()方法供调用它的方法调用
(a)为一级缓存上锁,开始操作一级缓存
(b)从一级缓存中获取Bean,如果获取到了直接返回,如果没获取到则经过一系列的安全校验后调用匿名内部类的getObject方法获取到Bean。
(c)标记上单例标识符(方便后续一级缓存的添加)
(d)调用afterSingletonCreation()方法完成善后(既然你的bean已经最终创建完成,所以到正在创建bean的集合中移除掉beanName)
(e)调用addSingleton() :Bean实例完成创建之后,只保留一级缓存一级注册beanName的顺序,其余的清除)
(B)获取赋值上bean
4.对创建的Bean实例对象进行类型检查
5.返回bean实例