spring源码解读之getBean方法(二)

前言

接着上一部分的内容,我们继续来研究getBean方法的源码

开始

上一讲我们讲到了getSingleton方法,接下来我们来看getObjectForBeanInstance(sharedInstance, name, beanName, null);这句代码

protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
			}
		}

		// Now we have the bean instance, which may be a normal bean or a FactoryBean.
		// If it's a FactoryBean, we use it to create a bean instance, unless the
		// caller actually wants a reference to the factory.
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd == null) {
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
			FactoryBean factory = (FactoryBean) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

可以看到这个方法其实是获取缓存中的bean实例,但是它还判断了bean是factoryBean类型的情况和bean是factoryBean本身的情况,因为factoryBean本身也是一个bean,只不过它有些特殊的功能,关于factoryBean,其实和BeanFactory的概念是很容易混淆的,有机会我还会写一篇关于factoryBean和BeanFactory的区别,现在先不讨论。

接下来,如果缓存中没有数据,那么会到上一层的beanFactory中去试图获得bean,其实最终还是会到这个doGetBean方法里来,如果上一层的beanFactory中拿不到bean,那么接下来会来到这段代码,这段代码非常的重要

try {
		final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
		checkMergedBeanDefinition(mbd, beanName, args);

		//检查是否有depends on
		// Guarantee initialization of beans that the current bean depends on.
		String[] dependsOn = mbd.getDependsOn();
		if (dependsOn != null) {
			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 {
					getBean(dep);
				}
				catch (NoSuchBeanDefinitionException ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
				}
			}
		}

		//创建bean实例
		// Create bean instance.
		if (mbd.isSingleton()) {
			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;
			}
		});
			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);
			}

		    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;
		}

这里面这句代码final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);就是去合并parent的属性进来。RootBeanDefinition是个什么类呢,我从网上找到了一个人的解释,我觉得挺到位的,贴出来给大家看

//简单的说:在多继承体系中,RootBeanDefinition代表的是当前初始化类的父类的BeanDefinition 若没有父类,那就是它自己嘛
public class RootBeanDefinition extends AbstractBeanDefinition {
	
	//BeanDefinitionHolder存储有Bean的名称、别名、BeanDefinition
	@Nullable
	private BeanDefinitionHolder decoratedDefinition;
	// AnnotatedElement 是java反射包的接口,通过它可以查看Bean的注解信息
	@Nullable
	private AnnotatedElement qualifiedElement;
	//允许缓存
	boolean allowCaching = true;
	//从字面上理解:工厂方法是否唯一
	boolean isFactoryMethodUnique = false;
	//封装了java.lang.reflect.Type,提供了泛型相关的操作
	@Nullable
	volatile ResolvableType targetType;
	//缓存class,表明RootBeanDefinition存储哪个类的信息
	@Nullable
	volatile Class resolvedTargetType;
	//缓存工厂方法的返回类型
	@Nullable
	volatile ResolvableType factoryMethodReturnType;

	/** Common lock for the four constructor fields below */
	final Object constructorArgumentLock = new Object();

	//缓存已经解析的构造函数或是工厂方法,Executable是Method、Constructor类型的父类
	@Nullable
	Executable resolvedConstructorOrFactoryMethod;
	//表明构造函数参数是否解析完毕
	boolean constructorArgumentsResolved = false;
	//缓存完全解析的构造函数参数
	@Nullable
	Object[] resolvedConstructorArguments;
	//缓存待解析的构造函数参数,即还没有找到对应的实例,可以理解为还没有注入依赖的形参
	@Nullable
	Object[] preparedConstructorArguments;

	/** Common lock for the two post-processing fields below */
	final Object postProcessingLock = new Object();

	//表明是否被MergedBeanDefinitionPostProcessor处理过
	boolean postProcessed = false;
	//在生成代理的时候会使用,表明是否已经生成代理
	@Nullable
	volatile Boolean beforeInstantiationResolved;

	//实际缓存的类型是Constructor、Field、Method类型
	@Nullable
	private Set externallyManagedConfigMembers;
	//InitializingBean中的init回调函数名——afterPropertiesSet会在这里记录,以便进行生命周期回调
	@Nullable
	private Set externallyManagedInitMethods;
	//DisposableBean的destroy回调函数名——destroy会在这里记录,以便进行生命周期回调
	@Nullable
	private Set externallyManagedDestroyMethods;

	//===========方法(只例举部分)
	// 由此看出,RootBeanDefiniton是木有父的
	@Override
	public String getParentName() {
		return null;
	}
	@Override
	public void setParentName(@Nullable String parentName) {
		if (parentName != null) {
			throw new IllegalArgumentException("Root bean cannot be changed into a child bean with parent reference");
		}
	}

	// 拿到class类型
	@Nullable
	public Class getTargetType() {
		if (this.resolvedTargetType != null) {
			return this.resolvedTargetType;
		}
		ResolvableType targetType = this.targetType;
		return (targetType != null ? targetType.resolve() : null);
	}

	@Override
	public RootBeanDefinition cloneBeanDefinition() {
		return new RootBeanDefinition(this);
	}
}

在经过getMergedLocalBeanDefinition(beanName)这个方法得到mbd之后,会去检查mbd中有没有dependsOn,因为需要控制bean的加载顺序,如果有dependsOn注解的话要先注册被依赖的那个bean,然后再getBean,如果没有dependsOn注解,那就是最普通的bean,那就要走到创建bean实例的代码段了

//这里创建完bean后直接放到缓存中
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;
}});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

 调用createBean方法最后会来到org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])这个方法中

@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		if (logger.isDebugEnabled()) {
			logger.debug("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// Make sure bean class is actually resolved at this point, and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
		Class resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.
		// 处理 lookup-method 和 replace-method 配置,Spring 将这两个配置统称为 override method
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// 在 bean 初始化前应用后置处理,如果后置处理返回的 bean 不为空,则直接返回
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
			// 调用doCreateBean 创建bean,关键中的关键,但是这个方法很复杂
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isDebugEnabled()) {
				logger.debug("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			// A previously detected exception with proper bean creation context already,
			// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}

 这个方法中,最重要的一句代码是Object beanInstance = doCreateBean(beanName, mbdToUse, args);这句代码是创建bean实例的代码,这个方法非常复杂,会涉及到bean的循环引用,属性的注入,后置处理器的使用等等,有关这些不在本次源码解读的范围内,就不详细去讲了,我就把代码贴出来简单讲解一下创建bean的实例主要分哪几个步骤

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			/**
			 * 创建 bean 实例,并将实例包裹在 BeanWrapper 实现类对象中返回。
			 * createBeanInstance中包含三种创建 bean 实例的方式:
			 *   1. 通过工厂方法创建 bean 实例
			 *   2. 通过构造方法自动注入(autowire by constructor)的方式创建 bean 实例
			 *   3. 通过无参构造方法方法创建 bean 实例
			 *
			 * 若 bean 的配置信息中配置了 lookup-method 和 replace-method,则会使用 CGLIB
			 * 增强 bean 实例。关于lookup-method和replace-method后面再说。
			 */
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();
		Class beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			//设置属性,非常重要
			populateBean(beanName, mbd, instanceWrapper);
			//执行后置处理器,aop就是在这里完成的处理
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

 到了这里,其实大家就可以看我之前的《一道面试题引发的spring源码阅读》这篇文章了,这篇文章就是从instanceWrapper = createBeanInstance(beanName, mbd, args);这个方法开始讲起的,调用过这个方法以后,实际上就已经可以拿到bean了,只不过这个bean是被包装类给包装起来的bean,再然后就是设置属性,执行后置处理器了,执行完后置处理器,整个bean就算实例化完成了,最后返回到getBean方法,加一个强制转换就可以得到对象了。

总结

经过两篇文章的分析,相信大家已经基本清楚了getBean方法的执行流程和调用的那些方法和方法的含义,同时也熟悉了spring了代码风格,就是不断的嵌套调用很多的继承加上很多的工厂很多的重载方法,有时间的话我还会解读spring如何解决bean的循环引用,beanFactory和FactoryBean的区别,属性注入,bean后置处理器等等的源码,希望大家多多关注多多支持,谢谢大家。

你可能感兴趣的:(spring,spring,java)