Spring 5 AbstractBeanFactory-- getType源码解析

相关源码注释

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
	@Nullable
	public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
    
    
		return getType(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
	@Nullable
	public 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用于表示null
		if (beanInstance != null && beanInstance.getClass() != NullBean.class) {
    
    
			//如果bean的单例对象是FactoryBean的实例 且 name不是FactoryBean的解引用
			if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
    
    
				//将beanInstance强转为FactoryBean,获取其创建出来的对象的类型并返回
				return getTypeForFactoryBean((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类型
				return getTypeForFactoryBean(beanName, mbd, allowFactoryBeanInit).resolve();
			}
			else {
    
    
				//如果是FactoryBean的解引用,就直接返回该beanName的最终bean类型
				return beanClass;
			}
		}
		else {
    
    //如果没有成功预测到beanName的最终bean类型 或者 最终bean类型不属于FactoryBean类型
			//如果name不是FactoryBean的解引用名,就直接返回该beanName的最终bean类型,否则返回null
			return (!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 String transformedBeanName(String name) {
    
    
		//去除开头的'&'字符,返回剩余的字符串得到转换后的Bean名称,然后通过递归形式在
		// aliasMap【别名映射到规范名称集合】中得到最终的规范名称
		return canonicalName(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
	 */
	public static String transformedBeanName(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>
	 * */
	private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
	
/**
	 * Determine the raw name, resolving aliases to canonical names.
	 * <p>确定原始名称,将别名解析为规范名称</p>
	 * @param name the user-specified name - 用户指定的名称
	 * @return the transformed name - 转换后的名称
	 */
	public String canonicalName(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拿到C
		do {
    
    
			//通过 规范名称 从 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}
	 */
	@Nullable
	protected Object getSingleton(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
	 */
	public static boolean isFactoryDereference(@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
	 */
	@Nullable
	protected 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 中是个抽象方法

扫描二维码关注公众号,回复: 12430945 查看本文章
/**
	 * 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
	 */
	protected abstract boolean containsBeanDefinition(String beanName);

具体由 DefaultListableBeanFactory 实现

/**
	 * Map of bean definition objects, keyed by bean name.
	 * <p>Bean定义对象的映射,以Bean名称为键</p>
	 * */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
	
/**
	 * 本地工厂中BeanDefinition对象映射【beanDefinitionMap】中是否存在beanName该键名
	 * @param beanName the name of the bean to look for -- 要寻找的bean名
	 */
	@Override
	public boolean containsBeanDefinition(String beanName) {
    
    
		//如果beanName为null,抛出异常
		Assert.notNull(beanName, "Bean name must not be null");
		//从Beand定义对象映射中判断beanName是否存在该键
		return this.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
	 */
	@Nullable
	protected 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中以备将来使用。
		return resolveBeanClass(mbd, beanName, typesToMatch);
	}

resolveBeanClass(mbd, beanName, typesToMatch);

Spring 5 AbstractBeanFactory – resolveBeanClass源码解析

猜你喜欢

转载自blog.csdn.net/qq_30321211/article/details/108348807