Spring 5 AbstractBeanFactory-- getType源码解析

2022-06-28 07:55:16

相关源码注释

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将针对给定名称返回的对象 的类型.
逻辑步骤总结:

  1. 获取name对应的规范名称【全类名】,包括以’&'开头的name。然后将结果赋值给变量beanName
  2. 获取beanName注册的单例对象,但不会导致单例对象的创建,如果成功获取到且该单例对象 又不是NullBean
    1. 如果bean的单例对象是FactoryBean的实例 且 name不是FactoryBean的解引用名, 将beanInstance强转为FactoryBean,获取其创建出来的对象的类型并返回
    2. 否则获取beanInstance的类型并返回
  3. 获取该工厂的父级bean工厂,成功获取到了且该bean工厂包含具有beanName的bean定义, 就从父级bean工厂中获取name的全类名的bean类型并返回,【递归】
  4. 获取beanName对应的合并RootBeanDefinition的Bean定义持有者,通过持有者的合并的RootBeanDefinitio获取所对应bean名的 最终bean类型,而这类型不属于FactoryBean类型的话就返回出去。
  5. 尝试预测beanName的最终bean类型,如果该类型属于FactoryBean类型
    1. 如果name不是FactoryBean的解引用名,则尽可能的使用beanName和mbd去获取FactoryBean定义的bean类型。
    2. 如果是FactoryBean的解引用,就直接返回该beanName的最终bean类型
  6. 如果没有成功预测到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名称【可能是全类名】

  1. 如果name为null,抛出异常
  2. 如果name不是以’&'开头,就直接返回
  3. 从具有FactoryBean前缀的名称缓存到剥离的名称的ConcurrentHashMap【transformedBenaNameCache】 中获取bean名对应的转换后的名称并返回
  4. 获取不到时就构建一个:从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注册的(原始)单例对象:

  1. 从单例对象的高速缓存【singletonObjects】中获取beanName的单例对象,赋值为【singletonObject】
  2. 如果单例对象没成功获取,并且 baneName 是正在被创建:
    1. 同步,以singletonObjects作为锁
    2. 从早期单例对象的高速缓存【earlySingletonObjects】中获取bean对象,赋值为【singletonObject】
    3. 如果singletonObject为null,且允许创建早期引用:
    4. 从单例工厂的缓存【singletonFactories】中获取beanName的单例工厂对象,赋值给【singletonFactory】
    5. 如果singletonFactory不为null:
      1. 从singletonFactory中获取该beanName的单例对象,作为singletonObject
      2. 添加beanName和singletonObject到 早期单例对象高速缓存【earlySingletonObjects】中
      3. 从单例对象工厂缓存【singletonFactories】中移除beanName的单例对象工厂
  3. 返回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实例的类型)。大概逻辑:

  1. 如果成功获取到mbd的目标类型【RootBeanDefinition#getTargetType】,就将其返回出去
  2. 如果mbd有设置mbd的工厂方法名,则直接返回 null
  3. 返回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);}

resolveBeanClass(mbd, beanName, typesToMatch);

Spring 5 AbstractBeanFactory – resolveBeanClass源码解析

  • 作者:czb彬
  • 原文链接:https://blog.csdn.net/qq_30321211/article/details/108348807
    更新时间:2022-06-28 07:55:16