spring源码09: getBean

直接跟踪getBean的代码

MyBean myTestBean = (MyBean) bf.getBean("myBean");

@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
	return doGetBean(name, requiredType, null, false);
}

先打个预防针,以下代码第一次看肯定会一头雾水。这部分代码更像是总纲,很多地方都需要在后面详细讲解。因此一头雾水不要紧,多看几遍,然后往后面看,之后回过头来会清楚的多

// AbstractBeanFactory.java
	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

		/**
		 * 1. 转换beanName,存在一下2种情况
		 * 		1.当获取的是工厂而非bean时,beanName会带上&,此时需要先去掉&
		 * 		2.如果是别名,将别名转化为真实的beanName
 		 */
		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		// 2. 尝试从缓存中获取bean
		Object sharedInstance = getSingleton(beanName);
		// 存在缓存的情况
		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");
				}
				// 该bean直接通过缓存获取到,且不在循环引用的创建过程中
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			/**
			 * 返回对应的最终bean
			 * 例如当一个类继承了FactoryBean,xml文件配置如下:
			 * 	<bean id="car" class="CarFactoryBean">
			 * 则返回的应该是CarFactoryBean中getObject()的值,而非CarFactoryBean本身
			 */
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			// 3. spring只能尝试解决单例的循环依赖,原型模式下循环依赖是无解的,只能直接报错
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			// 4. 当parentBeanFactory不为空,且该当前bean还从未被加载过也就是说xml里面根本就没有这个beanName(这一句是非常关键的),则尝试去parentBeanFactory中找找看
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					// 直接递归调用重载的方法进行查找
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					// 参数不为空,则委托parentBeanFactory使用显式参数调动
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					// 参数为空,则使用标准的getBean方法获取bean
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					// 否则使用默认的getBean方法
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

			// 当前目的不单做类型检测还要创建bean,记录bean被创建
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
				// 5. 在第一阶段生产的数据均为GenericBeanDefinition,beanName完全有可能是子bean,在这里将会合并父bean并转换成RootBeanDefinition再进行创建
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					// 6. 如果存在依赖,则递归的调用该方法进行创建依赖的bean
					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);
						try {
							// 递归调用创建依赖的bean
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				// Create bean instance.
				// 7. 单例情况下
				if (mbd.isSingleton()) {
					/**
					 * 核心代码,spring4.x中是这么写的,会更容易理解一点
					 * sharedInstance = getSingleton(beanName, new ObjectFactory<object>() {
					 * 		getObject() {
					 * 			return createBean(beanName, mbd, args);
					 * 		}
					 * 	}
					 * 	即getSingleton第二个参数为ObjectFactory对象
					 */
					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.
							destroySingleton(beanName);
							throw ex;
						}
					});
					/**
					 * 8. 返回对应的最终bean
					 * 例如当一个类继承了FactoryBean,xml文件配置如下:
					 * 	<bean id="car" class="CarFactoryBean">
					 * 则返回的应该是CarFactoryBean中getObject()的值,而非CarFactoryBean本身
					 */
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				// 原型模式下
				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;// 原型模式
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				// 指定scope模式的创建
				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, () -> {
							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.
		// 9. 检查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;
	}

  1. 转换为真实beanName
    由于传入的beanName可能带&前缀需要获取工厂,也有可能是别名。因此需要做以下转换,找出真实的beanName
	protected String transformedBeanName(String name) {
		// 先调用transformedBeanName去除前缀,再调用canonicalName替换别名
		return canonicalName(BeanFactoryUtils.transformedBeanName(name));
	}

	// 去除前缀
	public static String transformedBeanName(String name) {
		Assert.notNull(name, "'name' must not be null");
		// FACTORY_BEAN_PREFIX = "&",不包含&前缀直接返回
		if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
			return name;
		}
		return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
			do {
				// 去除FACTORY_BEAN_PREFIX前缀,知道不包含前缀
				beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
			}
			while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
			return beanName;
		});
	}

	// 替换别名
	public String canonicalName(String name) {
		String canonicalName = name;
		// Handle aliasing...
		String resolvedName;
		do {
			// 通过aliasMap获取beanName,直到不再有别名
			resolvedName = this.aliasMap.get(canonicalName);
			// 可能存在A->B->C->D,所以需要一直循环直到没有别名位置
			if (resolvedName != null) {
				canonicalName = resolvedName;
			}
		}
		while (resolvedName != null);
		return canonicalName;
	}

  1. 尝试从缓存中获取bean,缓存主要有2个作用
    2.1 创建bean很耗性能,因此spring默认模式就是单例模式。单例模式下spring创建bean以后还会将其缓存到Map中以提高性能,当然也是为了确保单例模式下bean的唯一性。详见:spring源码10: spring从缓存中获取bean
    2.2 解决循环依赖(仅限单例),即A依赖B,B又依赖A造成无限循环的问题。Spring的做法是在A实例化以后,填充属性以及初始化之前,就将A的引用提前暴露到缓存中。之后A执行填充属性,发现需要依赖B所以创建B,当B创建时发现需要依赖A则直接取A提前曝光的引用完成创建。而后A则继续执行自己的初始化完成创建。(循环依赖时spring源码的重点,也是面试最喜欢问的东西,内容比较多,这里看的一头雾水不要紧,后面会有专门讲解,详见:spring源码13: spring 循环依赖

  1. 原型模式循环依赖检测
    spring只会处理单例情况下的循环依赖,原型模式是无解的,只能抛出异常。详见:spring源码13: spring 循环依赖
    既然该模式无解,那么spring是如何检测?我们假设存在2个原型模式的类A跟类B,他们互相引用
    循环依赖检测.jpg
		// 3. spring只能尝试解决单例的循环依赖,原型模式下循环依赖是无解的,只能直接报错
		if (isPrototypeCurrentlyInCreation(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	protected boolean isPrototypeCurrentlyInCreation(String beanName) {
		// 获取原型模式正在创建的所有beanName
		Object curVal = this.prototypesCurrentlyInCreation.get();
		// 只要当前的beanName存在curVal中,说明发生循环依赖
		return (curVal != null &&
				(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
	}

  1. 尝试从parentBeanFactory获取
    这里的判断条件很重要,if (parentBeanFactory != null && !containsBeanDefinition(beanName)),第一个条件没什么好说的,如果parentBeanFactory都不存在那还获取个龟龟。第二个条件说明beanName不在BeanDefinition集合中,说明没有被解析过,也就是在xml或者注解中就找不到这个beanName,那么我们也只能去父类中递归寻找了,那不然也莫得办法了啊

  1. 转换GenericBeanDefinition
    第一阶段产生的BeanDefinition均是GenericBeanDefinition这种类型,接下去要进行bean的创建了。这里的BeanDefinition完全有可能是子类,缺少父类的信息,并不是究极完整体,因此我们需要合并继承父类,做完合并后转成RootBeanDefiniton,因为后续都是用RootBeanDefiniton进行创建的

  1. 创建依赖
    这里的依赖跟我们所说的依赖注入@Autowired是两码事,不要混淆。这里指的是@DependOn或者depend-on标签所标记的依赖。该标签是为了控制bean的创建顺序,比如我们的Dao层创建顺序肯定要在DataSource之后,因此在我们的bean还未create的时候,所depend-onbean就应该先调用getBean进行创建。详细参考:denpend-on标签
// 6. 如果存在依赖,则递归的调用该方法进行创建依赖的bean
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);
	try {
		// 递归调用创建依赖的bean
		因此,虽然递归调用创建了依赖的bean,但是并没有去获取它进行注入,比如:Object depBean = getBean(dep)
		我们的目的只是为了确保依赖的dep能够优先于当前bean创建
		getBean(dep);
	}
	catch (NoSuchBeanDefinitionException ex) {
		throw new BeanCreationException(mbd.getResourceDescription(), beanName,
				"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
	}
}

  1. bean的创建
    根据不同的scope会有不同的创建策略,这里我们专注单例模式的创建。这里也是spring最最核心的部分。详见spring 获取单例

  1. 获取最终的bean
    当我们获取到缓存中的bean时,这时候的bean有可能继承FactoryBean,而我们要的真正的bean则是getObject()方法所返回的bean,因此需要做一步转换。详见:spring源码11: spring获取单例

  1. 类型转换
    假设我们新建完的beanString类型,而我们要求返回的beanint类型,则spring会尽量帮我们转换成所需要的类型。spring做了很多转换器供使用,当然我们也可以自己定义。这里不做太多介绍。

spring创建bean是一个很复杂的过程,接下去将把重点放在循环依赖,和bean的创建上面。看完这部分源码感觉怎么样?是不是有一种被几百个人锤了的感觉?源码就是这样,被锤习惯了就好了…

发布了30 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/chaitoudaren/article/details/104833529