相关源码注释
ApplicationContext
Spring 5 DefaultResourceLoader 源码注释
Spring 5 AbstractApplicationContext 源码注释
BeanFactory
Spring 5 SimpleAliasRegistry 源码注释
Spring 5 DefaultSingletonBeanRegistry 源码注释
Spring 5 FactoryBeanRegistrySupport 源码注释
Spring 5 AbstractBeanFactory 源码注释
Spring 5 AbstractAutowireCapableBeanFactory 源码注释
Spring 5 DefaultLisbaleBeanFactory 源码注释
getType(factoryBeanName);
确定具有给定名称的bean类型(为了确定其对象类型,默认让FactoryBean以初始化)。
由 AbstractBeanFactory 实现 。
/**
* 确定具有给定名称的bean类型(为了确定其对象类型,默认让FactoryBean以初始化)。
*
* @param name the name of the bean to query -- 要查询的bean名
* @return Bean的类型;如果不确定,则为null
* @throws NoSuchBeanDefinitionException 如果没有给定名称的bean
* @see #getType(String, boolean)
*/@Override@Nullablepublic Class<?>getType(String name)throws NoSuchBeanDefinitionException{returngetType(name,true);}
getType(name, true);
确定具有给定名称的bean类型。更具体地说,确定getBean将针对给定名称返回的对象 的类型.
逻辑步骤总结:
- 获取name对应的规范名称【全类名】,包括以’&'开头的name。然后将结果赋值给变量beanName
- 获取beanName注册的单例对象,但不会导致单例对象的创建,如果成功获取到且该单例对象 又不是NullBean
- 如果bean的单例对象是FactoryBean的实例 且 name不是FactoryBean的解引用名, 将beanInstance强转为FactoryBean,获取其创建出来的对象的类型并返回
- 否则获取beanInstance的类型并返回
- 获取该工厂的父级bean工厂,成功获取到了且该bean工厂包含具有beanName的bean定义, 就从父级bean工厂中获取name的全类名的bean类型并返回,【递归】
- 获取beanName对应的合并RootBeanDefinition的Bean定义持有者,通过持有者的合并的RootBeanDefinitio获取所对应bean名的 最终bean类型,而这类型不属于FactoryBean类型的话就返回出去。
- 尝试预测beanName的最终bean类型,如果该类型属于FactoryBean类型
- 如果name不是FactoryBean的解引用名,则尽可能的使用beanName和mbd去获取FactoryBean定义的bean类型。
- 如果是FactoryBean的解引用,就直接返回该beanName的最终bean类型
- 如果没有成功预测到beanName的最终bean类型 或者 最终bean类型不属于FactoryBean类型, 再加上如果name不是FactoryBean的解引用名,就直接返回该beanName的最终bean类型,否则返回null
/**
* 确定具有给定名称的bean类型。更具体地说,确定getBean将针对给定名称返回的对象 的类型.
* </p>
* @param name the name of the bean to query -- 要查询的bean名
* @param allowFactoryBeanInit whether a {@code FactoryBean} may get initialized
* just for the purpose of determining its object type
* -- {@code FactoryBean}是否可以初始化仅仅是为了确定其对象类型
* @return
* @throws NoSuchBeanDefinitionException
*/@Override@Nullablepublic Class<?>getType(String name,boolean allowFactoryBeanInit)throws NoSuchBeanDefinitionException{//获取name对应的规范名称【全类名】,包括以'&'开头的name
String beanName=transformedBeanName(name);// Check manually registered singletons.// 检查手动注册的单例// 获取beanName注册的单例对象,但不会创建早期引用
Object beanInstance=getSingleton(beanName,false);//如果成功获取到beanName的单例对象,且 该单例对象又不是NullBean,NullBean用于表示nullif(beanInstance!= null&& beanInstance.getClass()!= NullBean.class){//如果bean的单例对象是FactoryBean的实例 且 name不是FactoryBean的解引用if(beanInstanceinstanceofFactoryBean&&!BeanFactoryUtils.isFactoryDereference(name)){//将beanInstance强转为FactoryBean,获取其创建出来的对象的类型并返回returngetTypeForFactoryBean((FactoryBean<?>) beanInstance);}else{//获取beanInstance的类型并返回return beanInstance.getClass();}}// No singleton instance found -> check bean definition.// 找不到单例实例 -> 检查bean定义//获取该工厂的父级bean工厂
BeanFactory parentBeanFactory=getParentBeanFactory();//如果成功获取到了父级bean工厂 且 该bean工厂包含具有beanName的bean定义if(parentBeanFactory!= null&&!containsBeanDefinition(beanName)){// No bean definition found in this factory -> delegate to parent.// 在该工厂中找不到bean定义 -> 委托给父对象// originalBeanName:获取name对应的规范名称【全类名】,如果name前面有'&',则会返回'&'+规范名称【全类名】// 从父级bean工厂中获取name的全类名的bean类型,【递归】return parentBeanFactory.getType(originalBeanName(name));}//获取beanName对应的合并RootBeanDefinition,如果bean对应于子bean定义,则遍历父bean定义
RootBeanDefinition mbd=getMergedLocalBeanDefinition(beanName);// Check decorated bean definition, if any: We assume it'll be easier// to determine the decorated bean's type than the proxy's type.// 检查修饰的bean定义(如果有):我们假设确定修饰的bean类型比代理类型更容易// 获取mbd的Bean定义持有者
BeanDefinitionHolder dbd= mbd.getDecoratedDefinition();//如果成功获取到mbd的Bean定义持有者 且 name不是FactoryBean的解引用// FactoryBean的解引用指的是FactoryBean使用getObject方法得到的对象if(dbd!= null&&!BeanFactoryUtils.isFactoryDereference(name)){//获取合并的RootBeanDefinition
RootBeanDefinition tbd=getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);//尝试预测dbd的bean名的最终bean类型
Class<?> targetClass=predictBeanType(dbd.getBeanName(), tbd);//如果成功预测到了bdd的bean名的最终bean类型 且 targetClass不属于FactoryBean类型if(targetClass!= null&&!FactoryBean.class.isAssignableFrom(targetClass)){//返回该预测到的dbd的bean名的最终bean类型return targetClass;}}//尝试预测beanName的最终bean类型
Class<?> beanClass=predictBeanType(beanName, mbd);// Check bean class whether we're dealing with a FactoryBean.// 检查bean类是否正在处理FactoryBean// 如果成功预测到beanName的最终bean类型 且 该类属于FactoryBean类型if(beanClass!= null&& FactoryBean.class.isAssignableFrom(beanClass)){//如果name不是FactoryBean的解引用名if(!BeanFactoryUtils.isFactoryDereference(name)){// If it's a FactoryBean, we want to look at what it creates, not at the factory class.// 如果是FactoryBean,则我们要查看它创建的内容,而不是工厂类//尽可能的使用beanName和mbd去获取FactoryBean定义的bean类型returngetTypeForFactoryBean(beanName, mbd, allowFactoryBeanInit).resolve();}else{//如果是FactoryBean的解引用,就直接返回该beanName的最终bean类型return beanClass;}}else{//如果没有成功预测到beanName的最终bean类型 或者 最终bean类型不属于FactoryBean类型//如果name不是FactoryBean的解引用名,就直接返回该beanName的最终bean类型,否则返回nullreturn(!BeanFactoryUtils.isFactoryDereference(name)? beanClass: null);}}
transformedBeanName(name);
去除name开头的’&‘字符,获取name最终的规范名称【最终别名或者是全类名】:去除开头的’&'字符,返回剩余的字符串得到转换后的Bean名称, 然后通过递归形式在 aliasMap【别名映射到规范名称集合】中得到最终的规范名称
/**
* Return the bean name, stripping out the factory dereference prefix if necessary,
* and resolving aliases to canonical names.
* <p>返回Bean名称,如果必要,去除工厂取消前缀,并将别名解析为规范名称</p>
* @param name the user-specified name - 用户指定的名称
* @return the transformed bean name - 转换后的bena名称
*/protected StringtransformedBeanName(String name){//去除开头的'&'字符,返回剩余的字符串得到转换后的Bean名称,然后通过递归形式在// aliasMap【别名映射到规范名称集合】中得到最终的规范名称returncanonicalName(BeanFactoryUtils.transformedBeanName(name));}
BeanFactoryUtils.transformedBeanName(name)
去除开头的’&'字符,返回剩余的字符串作为转换后的Bean名称【可能是全类名】
- 如果name为null,抛出异常
- 如果name不是以’&'开头,就直接返回
- 从具有FactoryBean前缀的名称缓存到剥离的名称的ConcurrentHashMap【transformedBenaNameCache】 中获取bean名对应的转换后的名称并返回
- 获取不到时就构建一个:从name的开头位置去掉’&’,再重新检查是否还是以’&‘开头,是的话就再截直到没有出现’&'开头为止。所得到 的字符串就是Bean名称【可能是全类名】
/**
* Return the actual bean name, stripping out the factory dereference
* prefix (if any, also stripping repeated factory prefixes if found).
* <p>返回实际的bean名称,删除工厂取消引用前缀(如果有的话,还删除重复的
* 工厂前缀(如果找到))</p>
* <p>用于获取以'&'开头的name对应的bean名,如果bean不是'&'开头,就直接返回该name</p>
* @param name the name of the bean - bean名
* @return the transformed name - 转换后的名称
* @see BeanFactory#FACTORY_BEAN_PREFIX
*/publicstatic StringtransformedBeanName(String name){//如果bean名为null,抛出异常
Assert.notNull(name,"'name' must not be null");//如果bean名不是以'&'开头,就直接返回if(!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)){return name;}//从transformedBenaNameCache中获取bean名对应的转换后的名称return transformedBeanNameCache.computeIfAbsent(name, beanName->{//从beanName的开头位置去掉'&',并重新赋值给beanName,再重新检查是还是以'&'开头,是的话就再截// 知道开头不是以'&'开头后,加入到transformedBeanNameCache中do{
beanName= beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());}while(beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));return beanName;});}
canonicalName(name)
获取name的最终别名或者是全类名。通过递归形式在aliasMap【别名映射到规范名称集合】中得到最终的规范名称
由 SimpleAliasRegistry 实现。
/**
* Map from alias to canonical name.
* <p>从别名映射到规范名称</p>
* <p>整个Map数据结构应该要抽象理解为一个二维数组,因为在检索别名的时候,是可以通过别名查别名的。</p>
* <p>举个栗子:
* <ol>
* <li>A是B的别名,C是B的别名,存放到aliasMap中的数据结构就是:[{key=B,val=A},{key=C,val=B}]</li>
* <li>当要获取A的所有别名[B,C]时:先获取A的Key->B,则通过递归形式获取B的key->C。</li>
* </ol>
* </p>
* */privatefinal Map<String, String> aliasMap=newConcurrentHashMap<>(16);/**
* Determine the raw name, resolving aliases to canonical names.
* <p>确定原始名称,将别名解析为规范名称</p>
* @param name the user-specified name - 用户指定的名称
* @return the transformed name - 转换后的名称
*/public StringcanonicalName(String name){//规范名称初始化化传入的name
String canonicalName= name;// Handle aliasing... 处理别名
String resolvedName;//从下面代码可以看出,aliasMap的存储形式是:// C是真正的规范名称,A,B都是别名:// aliasMap={key:A,val:B;key:B,val:C},通过A拿到B,再通过B拿到Cdo{//通过 规范名称 从 aliasMap中获取解析后的名称
resolvedName=this.aliasMap.get(canonicalName);//如果找到了解析后的名称if(resolvedName!= null){//规范名称重新赋值为解析后名称
canonicalName= resolvedName;}}//只要找到了解析后的名称while(resolvedName!= null);return canonicalName;}
getSingleton(beanName, false);
获取以beanName注册的(原始)单例对象:
- 从单例对象的高速缓存【singletonObjects】中获取beanName的单例对象,赋值为【singletonObject】
- 如果单例对象没成功获取,并且 baneName 是正在被创建:
- 同步,以singletonObjects作为锁
- 从早期单例对象的高速缓存【earlySingletonObjects】中获取bean对象,赋值为【singletonObject】
- 如果singletonObject为null,且允许创建早期引用:
- 从单例工厂的缓存【singletonFactories】中获取beanName的单例工厂对象,赋值给【singletonFactory】
- 如果singletonFactory不为null:
- 从singletonFactory中获取该beanName的单例对象,作为singletonObject
- 添加beanName和singletonObject到 早期单例对象高速缓存【earlySingletonObjects】中
- 从单例对象工厂缓存【singletonFactories】中移除beanName的单例对象工厂
- 返回singletonObject
/**
* Return the (raw) singleton object registered under the given name.
* <p>返回以给定名称注册的(原始)单例对象,如果单例对象没有找到,并且beanName存在
* 正在创建的Set集合中</p>
* <p>Checks already instantiated singletons and also allows for an early
* reference to a currently created singleton (resolving a circular reference).
* <p>检查已经实例化的单例,并且还允许对当前的单例的早期引用(解析循环引用)</p>
* @param beanName the name of the bean to look for - 要寻找的bean名
* @param allowEarlyReference whether early references should be created or not
* - 是否应创建早期引用
* @return the registered singleton object, or {@code null} if none found
* - 注册的单例对象;如果找不到,则为{@code null}
*/@Nullableprotected ObjectgetSingleton(String beanName,boolean allowEarlyReference){//从单例对象的高速缓存中获取beanName的单例对象
Object singletonObject=this.singletonObjects.get(beanName);//如果单例对象没有找到,并且 baneName 是正在被创建if(singletonObject== null&&isSingletonCurrentlyInCreation(beanName)){//同步,以singletonObjects作为锁synchronized(this.singletonObjects){//从早期单例对象的高速缓存中获取bean对象
singletonObject=this.earlySingletonObjects.get(beanName);//如果获取不了bean的单例对象,且允许创建早期引用if(singletonObject== null&& allowEarlyReference){//从单例工厂的缓存中获取beanName的单例工厂对象
ObjectFactory<?> singletonFactory=this.singletonFactories.get(beanName);//如果beanName的单例工厂对象找到了if(singletonFactory!= null){//从beanName的单例工厂对象中获取该beanName的单例对象
singletonObject= singletonFactory.getObject();//下面的操作主要是为了防止beanName对应的对象重复构建//添加beanName和其对应的beanName单例对象到 早期单例对象高速缓存中this.earlySingletonObjects.put(beanName, singletonObject);//从单例对象工厂缓存中移除beanName的单例对象工厂this.singletonFactories.remove(beanName);}}}}//返回beanName对应的单例对象return singletonObject;}
BeanFactoryUtils.isFactoryDereference(name)
返回给定名称是否为FactoryBean的解引用.判断依据:name是以’&'开头,就是FactoryBean的解引用
/**
* Return whether the given name is a factory dereference
* (beginning with the factory dereference prefix).
* <p>返回给定名称是否为FactoryBean的解引用名.(从FactoryBean的解引用前缀开始)</p>
* @param name the name of the bean -- bean名
* @return whether the given name is a factory dereference -- 给定名称是否为BeanFactory的解引用
* @see BeanFactory#FACTORY_BEAN_PREFIX
*/publicstaticbooleanisFactoryDereference(@Nullable String name){//如果有传入bean名且bean名是以'&'开头,则返回true,表示是BeanFactory的解引用,否则// 返回false,表示不是BeanFactory的解引用return(name!= null&& name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));}
getTypeForFactoryBean((FactoryBean<?>) beanInstance)
确定给定FactoryBean的创建出来的对象的类型,将调用factoryBean的getObjectType所得到结果返回出去
/**
* Determine the type for the given FactoryBean.
* <p>确定给定FactoryBean的创建出来的对象的类型,将调用factoryBean的getObjectType所
* 得到结果返回出去</p>
* @param factoryBean the FactoryBean instance to check -- 要检查的FactoryBean实例
* @return the FactoryBean's object type,
* or {@code null} if the type cannot be determined yet
* -- FactoryBean的对象类型;如果尚不能确定类型,则返回null
*/@Nullableprotected Class<?>getTypeForFactoryBean(final FactoryBean<?> factoryBean){try{//如果成功获取到系统的安全管理器if(System.getSecurityManager()!= null){//使用特权的方式获取factoryBean的创建对象的类型并返回return AccessController.doPrivileged((PrivilegedAction<Class<?>>)
factoryBean::getObjectType,getAccessControlContext());}else{//获取factoryBean的创建对象的类型并返回return factoryBean.getObjectType();}}//捕获所有异常,一般在FactoryBean的getObjectType实现中抛出catch(Throwable ex){// Thrown from the FactoryBean's getObjectType implementation.// 从FactoryBean的getObjectType实现抛出// 日志信息:尽管合同上如果尚不能确定其对象的类型,则返回null,当FactoryBean从getObjectType引发了异常。
logger.info("FactoryBean threw exception from getObjectType, despite the contract saying "+"that it should return null if the type of its object cannot be determined yet", ex);return null;}}
containsBeanDefinition(beanName)
在 AbstractBeanFactory 中是个抽象方法
/**
* Check if this bean factory contains a bean definition with the given name.
* Does not consider any hierarchy this factory may participate in.
* Invoked by {@code containsBean} when no cached singleton instance is found.
* <p>该BeanFactory是否包含beanName的BeanDefinition对象。不考虑工厂可能参与的任何层次结构。
* 未找到缓存的单例实例时,由{@code containsBena}调用。</p>
* <p>Depending on the nature of the concrete bean factory implementation,
* this operation might be expensive (for example, because of directory lookups
* in external registries). However, for listable bean factories, this usually
* just amounts to a local hash lookup: The operation is therefore part of the
* public interface there. The same implementation can serve for both this
* template method and the public interface method in that case.
* <p>根据具体bean工厂实现的性质,此操作可能很昂贵(例如,由于在外部注册表中进行目录
* 寻找)。但是,对应可列出的bean工厂,这通常只相当于本地哈希查找:因此,该操作是该处
* 工厂接口的一部分。在这种情况下,该模板方法和公共接口方法都可以使用相同的实现。</p>
* @param beanName the name of the bean to look for - 要查找的bean名
* @return if this bean factory contains a bean definition with the given name
* - 如果此bean工厂包含具有给定名称的bean定义。
* @see #containsBean
* @see org.springframework.beans.factory.ListableBeanFactory#containsBeanDefinition
*/protectedabstractbooleancontainsBeanDefinition(String beanName);
具体由 DefaultListableBeanFactory 实现
/**
* Map of bean definition objects, keyed by bean name.
* <p>Bean定义对象的映射,以Bean名称为键</p>
* */privatefinal Map<String, BeanDefinition> beanDefinitionMap=newConcurrentHashMap<>(256);/**
* 本地工厂中BeanDefinition对象映射【beanDefinitionMap】中是否存在beanName该键名
* @param beanName the name of the bean to look for -- 要寻找的bean名
*/@OverridepublicbooleancontainsBeanDefinition(String beanName){//如果beanName为null,抛出异常
Assert.notNull(beanName,"Bean name must not be null");//从Beand定义对象映射中判断beanName是否存在该键returnthis.beanDefinitionMap.containsKey(beanName);}
getMergedLocalBeanDefinition(beanName)
Spring 5 AbstractBeanFactory – getMergedLocalBeanDefinition 源码解析
getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd)
Spring 5 AbstractBeanFactory – getMergedLocalBeanDefinition 源码解析
predictBeanType(dbd.getBeanName(), tbd);
预测mdb所指的bean的最终bean类型(已处理bean实例的类型)。大概逻辑:
- 如果成功获取到mbd的目标类型【RootBeanDefinition#getTargetType】,就将其返回出去
- 如果mbd有设置mbd的工厂方法名,则直接返回 null
- 返回resolveBeanClass(RootBeanDefinition,String,Class<?>…)的执行结果, 主要是为mbd解析bean类,将beanName解析为Class引用(如果需要),并将解析后的Class存储 在mbd中以备将来使用。
/**
* Predict the eventual bean type (of the processed bean instance) for the
* specified bean. Called by {@link #getType} and {@link #isTypeMatch}.
* Does not need to handle FactoryBeans specifically, since it is only
* supposed to operate on the raw bean type.
* <p>预测指定bean的最终bean类型(已处理bean实例的类型)。
* 通过调用getType和isTypeMatch。不需要专门处理FactoryBeans,因为它仅应在
* 原始bean类型上运行</p>
* <p>This implementation is simplistic in that it is not able to
* handle factory methods and InstantiationAwareBeanPostProcessors.
* It only predicts the bean type correctly for a standard bean.
* To be overridden in subclasses, applying more sophisticated type detection.
* <p>此实现非常简单,因为它无法处理工厂方法和InstantiationAwareBeanProcess.
* 它只能为标准Bean正确预测Bean类型。要在子类中覆盖,请应用更复杂的类型检查</p>
* @param beanName the name of the bean -- bean名,用于发生异常时,描述异常信息
* @param mbd the merged bean definition to determine the type for
* -- 合并的bean定义以确定其类型
* @param typesToMatch
* 要匹配的类型,用于当该工厂有临时类加载器且该类加载器属于DecoratingClassLoader实例时,
* 对这些要匹配的类型进行在临时类加载器中的排除,以交由父ClassLoader以常规方式处理
* 默认情况下父classLoader是线程上下文类加载器】
* <br/>
* the types to match in case of internal type matching purposes
* (also signals that the returned {@code Class} will never be exposed to application code)
* -- 内部类型培评时要匹配的类型(也表示返回的Class永远不会保留应用程序代码)
* @return the type of the bean, or {@code null} if not predictable
* -- Bean的类型;如果不可预测,则为null
*/@Nullableprotected Class<?>predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch){//获取mbd的目标类型
Class<?> targetType= mbd.getTargetType();//如果成功获得mbd的目标类型if(targetType!= null){//返回 mbd的目标类型return targetType;}//如果有设置mbd的工厂方法名if(mbd.getFactoryMethodName()!= null){//返回null,表示不可预测return null;}//为mbd解析bean类,将beanName解析为Class引用(如果需要),并将解析后的Class存储在mbd中以备将来使用。returnresolveBeanClass(mbd, beanName, typesToMatch);}