Spring 源码分析一 :bean的加载过程

一、前言

本文是笔者阅读Spring源码的记录文章,由于本人技术水平有限,在文章中难免出现错误,如有发现,感谢各位指正。在阅读过程中也创建了一些衍生文章,衍生文章的意义是因为自己在看源码的过程中,部分知识点并不了解或者对某些知识点产生了兴趣,所以为了更好的阅读源码,所以开设了衍生篇的文章来更好的对这些知识点进行进一步的学习。

本文衍生篇:
1. Spring 源码分析衍生篇一 :FactoryBean介绍
2. Spring 源码分析衍生篇二 : Spring 中的循环依赖

二、简介

下面文章的内容,是基于上面衍生篇的内容来分析,如有不好理解内容,建议先查阅衍生篇内容。

1. DefaultSingletonBeanRegistry

我们首先需要了解DefaultSingletonBeanRegistry 类中的下面四个集合的作用如下在这里插入图片描述

  • singletonObjects : 用于保存BeanName和创建bean实例之间的关系,即缓存bean。 beanname -> instance
  • singletonFactories :用于保存BeanName和常见bean的工厂之间的关系。beanname-> ObjectFactory
  • earlySingletonObjects :也是保存BeanName和创建bean实例之间的关系,与singletonObjects 不同的是,如果一个单例bean被保存在此,则当bean还在创建过程中(比如 A类中有B类属性,当创建A类时发现需要先创建B类,这时候Spring又跑去创建B类,A类就会添加到该集合中,表示正在创建),就可以通过getBean方法获取到了,其目的是用来检测循环引用。
  • registeredSingletons :用来保存当前所有已经注册的bean

2. BeanDefinition

BeanDefinition 是一个接口,在Spring 中存在三种实现: RootBeanDefinitionChildBeanDefinition以及GenericBeanDefinition。三种实现均继承了AbstractBeanDefinition。顾名思义,BeanDefinition是bean的信息,一个BeanDefinition 描述和定义了创建一个bean需要的所有信息,属性,构造函数参数以及访问它们的方法。还有其他一些信息,比如这些定义来源自哪个类等等。
对于XML 配置方式的Spring方式来说, BeanDefinition 是配置文件 < bean > 元素标签在容器中的内容表示形式。< bean > 元素标签拥有class、scope、lazy-init等配置属性,BeanDefinition 则提供了相应的beanClass、scope、lazyinit属性,BeanDefinition 和 < bean > 中的属性是一一对应的。其中RootBeanDefinition 是最常用的实现类,一般对应< bean > 元素标签。

类似下图的定义: 在这里插入图片描述
具体属性释义请参考 : https://blog.csdn.net/andy_zhang2007/article/details/85381148

3. 搭建启动测试

我们新建一个项目,创建一个demoService。这里我为了省事就直接写了一个配置类加载。这个是为了引出我们来从getBean开始分析。

@SpringBootApplication
public class SpringbootDemoApplication {
    
    	

    public static void main(String[] args) {
    
    
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(DemoConfig.class);
        annotationConfigApplicationContext.getBean("demoService");
    }

}
@Configuration
public class DemoConfig {
    
    
    @Bean
    public DemoService demoService(){
    
    
        return new DemoServiceImpl();
    }
}

annotationConfigApplicationContext.getBean("demoService"); 最终会跳转到AbstractBeanFactory#doGetBean。所以我们这里直接来分析 AbstractBeanFactory#doGetBean

三、doGetBean整体分析

AbstractBeanFactory#doGetBean, 这个方法是一切的核心。

代码中是简略注释,后面对每一步进行详细解释。

	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    
    
		// 1. 提取出对应的beanName。
		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		// 2. 尝试从缓存获取或者singletonFacotries中的ObjectFactory中获取。后续细讲
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
    
    
			if (logger.isTraceEnabled()) {
    
    
				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");
				}
				else {
    
    
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			// 3. 返回对应的实例,有时候存在诸如BeanFactory的情况并不直接返回实例本身,而是返回指定方法返回的实例。这一步主要还是针对FactoryBean的处理。
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
    
    
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			// 4. 只有单例情况才会尝试解决循环依赖,原型模式直接抛出异常。因为原型模式无法解决循环依赖问题。
			if (isPrototypeCurrentlyInCreation(beanName)) {
    
    
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			// 5. 如果 beanDefinitionMap 中也就是在所有已经加载的类中不包含beanName,则尝试从parentBeanFactory中检测
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    
    
				// Not found -> check parent.
				// 递归到BeanFactory中检测
				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.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
    
    
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
    
    
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}
			// 如果不仅仅做类型检查则是创建bean,这里需要记录
			if (!typeCheckOnly) {
    
    
				markBeanAsCreated(beanName);
			}

			try {
    
    
				// 6. 将当前 beanName 的 BeanDefinition 和父类BeanDefinition 属性进行一个整合
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				// 7. 寻找bean的依赖
                // 获取初始化的依赖项
				String[] dependsOn = mbd.getDependsOn();
				// 如果需要依赖,则递归实例化依赖bean
				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);
						}
					}
				}

				// Create bean instance.
                // 8 针对不同的Scope 进行bean的创建
				// 实例化依赖的bean便可以实例化mdb本身了
				// singleton 模式的创建
				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()) {
    
    
					// Prototype 模式的创建
					// 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();
					// 指定scope上实例化bean
					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;
	}

综上所属,doGetBean的 大体流程如下:

  1. 将传入的beanName 转化为合适的beanName。因为这里可能传入bean的别名,比如 FactoryBean 这里就是传入 “&beanName” , 这一步就会将其转化为 “beanName”
  2. 尝试从单例缓存中获取 bean,主要是尝试从 singletonObjects 和 singletonFactories 中获取实例。(这一步中还使用了 earlySingletonObjects 来判断循环依赖的问题)
  3. 如果第二步获取到了bean,则会针对处理 FactoryBean 这种特殊情况,以获取到正确的bean。(因为Factorybean 的话可能需要将其 getObject 方法的返回值作为bean注入到容器中)。
  4. 如果第二步没有获取到bean,则会检测其原型模式下的循环依赖情况,如果原型模式下有循环依赖,则直接抛出异常,因为原型模式下无法解决循环依赖。
  5. 如果第四步没有抛出异常,则会判断 当前BeanFactory 中是否包含该beanName 的定义信息,如果不包含,则会递归去 parentBeanFactory 中去寻找beanName的定义信息.
  6. 随后查询beanName 的 BeanDefinition 是否具有 父类的BeanDefinition, 如果有,则将 父类的一些属性和子类合并,形成一个新的BeanDefinition : mdb
  7. 获取mdb中的 depends-on 属性,优先将依赖的bean创建,随后再创建当前bean。
  8. 到这一步,则说明当前bean尚未创建,则会根据 singleton 或者 prototype 或其他逻辑,走不同的流程来创建bean
  9. 创建bean结束后,根据调用者需要的类型进行一个类型转换。比如调用者希望返回一个Integer,这里得到的结果却是String,则会进行一个类型的转换。

下面是对每一个步骤的详解。

四、doGetBean - 步骤详解

1. 转换对应beanName - transformedBeanName

final String beanName = transformedBeanName(name);

这一步的目的是为了去除 beanName 的别名,这里的name传入的可能是 bean的别名,或者是FactoryBean。所以需要一系列的解析,解析包括

  1. 去除 FactoryBean 的修饰符。也就是说如果 name = “&name” 会去除& 使得 name = “name”。
  2. 取指定alias所表示的最终beanName。比如别名A指向B的bean,则会返回B。

2. 尝试从缓存中加载单例 - getSingleton

	Object sharedInstance = getSingleton(beanName);

单例的Spring在同一容器中只会创建一次(保存到单例缓存map中),后续再获取bean就直接从单例缓存中获取。这里的加载只是尝试加载,如果加载不成功则从singletonFactories 中加载。
因为在创建单例bean 的时候回存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,Spring 在创建bean的原则是不等bean 创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时需要依赖上一个bean,则直接使用ObjectFactory。

代码逻辑如下:

  1. 尝试从singletonObjects 中获取。获取不到说明该bean尚未创建成功。
  2. isSingletonCurrentlyInCreation 返回 true,则说明当前bean 的创建过程存在循环依赖,下面的逻辑就是为了尝试解决循环依赖
  3. 尝试从 earlySingletonObjects 中获取,获取不到说明该bean并未在创建过程中。(为了解决循环依赖的问题)
  4. allowEarlyReference = true时,这个是针对循环引用的操作,是允许循环引用。
  5. 随后 从singletonFactories 中加载beanFactory,并将结果保存到 earlySingletonObjects 中,同时将 singletonFactories 中关于bean的定义移除。(earlySingletonObjectssingletonFactories 互斥)

具体代码如下:

	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    
    
		// 尝试从单例缓存中加载。
		Object singletonObject = this.singletonObjects.get(beanName);
		
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    
    
			// 如果加载失败,则加锁进行接下来的处理
			synchronized (this.singletonObjects) {
    
    
				// 如果此时bean正在加载,则直接将singletonObject 返回。
				singletonObject = this.earlySingletonObjects.get(beanName);
				// allowEarlyReference = true 才会允许循环依赖
				if (singletonObject == null && allowEarlyReference) {
    
    
					// 当某些方法需要提前初始化的时候则会调用addSingletonFactory 将对应的ObjectFactory初始化策略存储在singletonFactories中
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
    
    
						// 调用预先设定的getObject方法
						singletonObject = singletonFactory.getObject();
						// 记录在缓存中,earlySingletonObjects 和 singletonFactories互斥
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

这里需要注意的是从 singletonFactories 中获取的是ObjectFactory。随后从中获取ObjectFactory.getObject()。 这里的目的是为了解决循环依赖,


3. 从bean 的实例中获取对象 - getObjectForBeanInstance

	bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);

当我们结束上一步之后,经过 sharedInstance != null && args == null 的判断后就会调用该方法。

作为上一步获取到的结果 sharedInstance 。我们需要判断其是否是FactoryBean 的 实现类,如果是,则需要将其getObject() 的结果注入。所以该方法的功能简单来说就是用来检测当前bean是否是FactoryBean类型的bean,如果是,则调用其getObject() 方法,并将其返回值作为bean。

关于FactoryBean的内容请参考 : https://blog.csdn.net/qq_36882793/article/details/105748071

代码逻辑大体如下:

  1. 判断是否需要获取 FactoryBean实例。 通过 BeanFactoryUtils.isFactoryDereference(name) 来判断
    判断name 是否以 & 开头。如果是则说明是想获取 FactoryBean 的实例,所以经过简单校验后就直接返回beanInstance。
  2. 经过第一步,现在可以确定,当前bean不是为了获取FactoryBean实现类,那么这个bean还可能是普通bean或者FactoryBean。if (!(beanInstance instanceof FactoryBean)) 判断如果不是FactoryBean则没必要进行下一步处理,直接返回即可。
  3. 这一步可以确定,这里的bean是 FactoryBean类型,并且name 是“beanName”,表明是想获取bean实例,而不是beanFactory实例,则将解析bean的工作委托给 getObjectFromFactoryBean完成。getObjectFromFactoryBean 方法对FactoryBean的解析还是在 中完成。(getObjectFromFactoryBean 这一步调用了ObjectFactory的后置处理器
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.
		// 1. 检测name 是否是想获取 工厂类(name 以 & 开头) 
		if (BeanFactoryUtils.isFactoryDereference(name)) {
    
    
			if (beanInstance instanceof NullBean) {
    
    
				return beanInstance;
			}
			// 以&开头又不是FactoryBean实现类,则抛出异常
			if (!(beanInstance instanceof FactoryBean)) {
    
    
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
			if (mbd != null) {
    
    
				mbd.isFactoryBean = true;
			}
			return beanInstance;
		}

		// 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.
		// 2. 判断如果beanInstance 不是 FactoryBean,就直接返回
		if (!(beanInstance instanceof FactoryBean)) {
    
    
			return beanInstance;
		}
		// 3. 到这一步就可以确定,当前beanInstance 是FactoryBean,并且需要获取getObject() 的结果
		Object object = null;
		if (mbd != null) {
    
    
			mbd.isFactoryBean = true;
		}
		else {
    
    
			// 尝试从缓存中加载bean
			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.
			// containsBeanDefinition 检测  beanDefinitionMap中也就是所有已经加载的类中检测是否定义beanName
			if (mbd == null && containsBeanDefinition(beanName)) {
    
    
				// 合并父类bean 定义的属性
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			// 4. 这一步中对FactoryBean进行了解析。
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

getObjectFromFactoryBean 方法中 调用 doGetObjectFromFactoryBean 方法进行了解析。
上面已经说了,因为这里的bean是FactoryBean,且并不是为了获取FactoryBean实例,所以会调用factory.getObject() 方法将得到的bean返回。


getObjectFromFactoryBean 代码如下

	protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    
    
		// 判断是否是单例模式
		if (factory.isSingleton() && containsSingleton(beanName)) {
    
    
			synchronized (getSingletonMutex()) {
    
    
				// 尝试从缓存中获取
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
    
    
					// 在这个方法中进行解析
					object = doGetObjectFromFactoryBean(factory, beanName);
					// Only post-process and store if not put there already during getObject() call above
					// (e.g. because of circular reference processing triggered by custom getBean calls)			
					// 因为是单例模式,所以要保证变量的全局唯一。所以这里如果缓存中已经创建好了bean则替换为已经创建好的bean
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
    
    
						object = alreadyThere;
					}
					else {
    
    
						if (shouldPostProcess) {
    
    
							if (isSingletonCurrentlyInCreation(beanName)) {
    
    
								// Temporarily return non-post-processed object, not storing it yet..
								return object;
							}
							beforeSingletonCreation(beanName);
							try {
    
    
								// 调用了ObjectFactory的后置处理器。
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
    
    
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
							finally {
    
    
								afterSingletonCreation(beanName);
							}
						}
						if (containsSingleton(beanName)) {
    
    
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				return object;
			}
		}
		else {
    
    
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
    
    
				try {
    
    
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
    
    
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			return object;
		}
	}

	....
	
	private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
			throws BeanCreationException {
    
    

		Object object;
		try {
    
    
			// 需要权限验证
			if (System.getSecurityManager() != null) {
    
    
				AccessControlContext acc = getAccessControlContext();
				try {
    
    
					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
    
    
					throw pae.getException();
				}
			}
			else {
    
    
				// 直接调用getObject方法。
				object = factory.getObject();
			}
		}
		catch (FactoryBeanNotInitializedException ex) {
    
    
			throw new BeanCurrentlyInCreationException(beanName, ex.toString());
		}
		catch (Throwable ex) {
    
    
			throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
		}

		// Do not accept a null value for a FactoryBean that's not fully
		// initialized yet: Many FactoryBeans just return null then.
		if (object == null) {
    
    
			if (isSingletonCurrentlyInCreation(beanName)) {
    
    
				throw new BeanCurrentlyInCreationException(
						beanName, "FactoryBean which is currently in creation returned null from getObject");
			}
			object = new NullBean();
		}
		return object;
	}

4 原型模式的依赖检查 - isPrototypeCurrentlyInCreation

if (isPrototypeCurrentlyInCreation(beanName)) {
    
    

在衍生篇中对循环依赖有过结介绍,简而言之就是 单例模式下才会尝试去解决循环依赖的问题,而原型模式则无法解决。也就是 isPrototypeCurrentlyInCreation 返回true,则抛出异常。
需要注意的是还有一个 方法是 判断单例模式的依赖检查 : isSingletonCurrentlyInCreation

5 检测 parentBeanFactory - if (parentBeanFactory != null && !containsBeanDefinition(beanName))

这一步的逻辑比较简单,如下:

  1. 首先通过 containsBeanDefinition(beanName) 方法判断当前beanFactory中是否有bean的定义,如果有,皆大欢喜。直接进入下一步。
  2. 如果没有,且 parentBeanFactory 不为空,则会通过递归的方式,尝试从 parentBeanFactory 中加载bean定义
// 5. 如果 beanDefinitionMap 中也就是在所有已经加载的类中不包含beanName,则尝试从parentBeanFactory中检测
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    
    
				// Not found -> check parent.
				// 递归到BeanFactory中检测
				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.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
    
    
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
    
    
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

其中 DefaultListableBeanFactory#containsBeanDefinition 代码如下

	@Override
	public boolean containsBeanDefinition(String beanName) {
    
    
		Assert.notNull(beanName, "Bean name must not be null");
		return this.beanDefinitionMap.containsKey(beanName);
	}

6 将当前 beanName 的 BeanDefinition 和父类BeanDefinition 属性进行一个整合

BeanDefinition 顾名思义,就是关于bean 的定义信息。通过xml的bean定义可以很清楚的看到一些属性定义。
在这里插入图片描述
所以这一步就是检查当前 BeanDefinition 是否有父BeanDefinition ,如果有将一些属性和当前bean合并,生成一个 RootBeanDefinition。

推荐阅读: https://blog.csdn.net/andy_zhang2007/article/details/86514320

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

getMergedLocalBeanDefinition -> getMergedBeanDefinition -> getMergedBeanDefinition。
这里直接来看 getMergedBeanDefinition 方法。

首先,mdb 即 MergedBeanDefinition 的缩写,即一个合并的beanDefinition。

	protected RootBeanDefinition getMergedBeanDefinition(
			String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
			throws BeanDefinitionStoreException {
    
    
		
		synchronized (this.mergedBeanDefinitions) {
    
    
			RootBeanDefinition mbd = null;
			RootBeanDefinition previous = null;

			// Check with full lock now in order to enforce the same merged instance.
			if (containingBd == null) {
    
    
				mbd = this.mergedBeanDefinitions.get(beanName);
			}

			if (mbd == null || mbd.stale) {
    
    
				previous = mbd;
				// 判断如果parentName为空则没必要进行合并了,直接克隆返回即可
				if (bd.getParentName() == null) {
    
    
					// Use copy of given root bean definition.
					if (bd instanceof RootBeanDefinition) {
    
    
						mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
					}
					else {
    
    
						mbd = new RootBeanDefinition(bd);
					}
				}
				else {
    
    
					// Child bean definition: needs to be merged with parent.
					BeanDefinition pbd;
					try {
    
    
						// 转换beanName
						String parentBeanName = transformedBeanName(bd.getParentName());
						// 递归调用,解析更上层的parent
						if (!beanName.equals(parentBeanName)) {
    
    
							pbd = getMergedBeanDefinition(parentBeanName);
						}
						else {
    
    
							BeanFactory parent = getParentBeanFactory();
							if (parent instanceof ConfigurableBeanFactory) {
    
    
								pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
							}
							else {
    
    
								throw new NoSuchBeanDefinitionException(parentBeanName,
										"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
										"': cannot be resolved without a ConfigurableBeanFactory parent");
							}
						}
					}
					catch (NoSuchBeanDefinitionException ex) {
    
    
						throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
								"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
					}
					// Deep copy with overridden values.
					// 深拷贝
					mbd = new RootBeanDefinition(pbd);
					mbd.overrideFrom(bd);
				}

				// Set default singleton scope, if not configured before.
				if (!StringUtils.hasLength(mbd.getScope())) {
    
    
					mbd.setScope(SCOPE_SINGLETON);
				}

				// A bean contained in a non-singleton bean cannot be a singleton itself.
				// Let's correct this on the fly here, since this might be the result of
				// parent-child merging for the outer bean, in which case the original inner bean
				// definition will not have inherited the merged outer bean's singleton status.
				if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
    
    
					mbd.setScope(containingBd.getScope());
				}

				// Cache the merged bean definition for the time being
				// (it might still get re-merged later on in order to pick up metadata changes)
				if (containingBd == null && isCacheBeanMetadata()) {
    
    
					this.mergedBeanDefinitions.put(beanName, mbd);
				}
			}
			if (previous != null) {
    
    
				copyRelevantMergedBeanDefinitionCaches(previous, mbd);
			}
			return mbd;
		}
	}

7 寻找依赖

这一步也是针对 BeanDefinition 的 depends-on 属性来说的(对应注解则是 @DependsOn。主要是 优先加载Bean 的 depends-on依赖。

因为bean 的初始化过程中很可能会用到某些属性,而某些属性很可能是动态配置的,并且配置成依赖于其他的bean,那么这个时候就有必要先加载依赖的bean,所以,在Spring的加载顺寻中,在初始化某一个bean的时候首先会初始化这个bean所对应的依赖。

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

注意:
@DependsOn:注解是在另外一个实例创建之后才创建当前实例,也就是,最终两个实例都会创建,只是顺序不一样
@ConditionalOnBean :注解是只有当另外一个实例存在时,才创建,否则不创建,也就是,最终有可能两个实例都创建了,有可能只创建了一个实例,也有可能一个实例都没创建

8 针对不同的Scope 进行bean的创建

这里很明显,针对不同的Scope进行不同的初始化操作。创建bean 的过程也很复杂,这里打算开新篇讲解(暂未成篇)。

下面代码就是根据 Singleton、Prototype 或者其他Scope 走不同的流程创建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);
					}
				}

9 类型转换

到这里整个流程基本就结束了。通常对该方法的调用参数 requiredType 是null,。但某些情况可能会出现返回的bean是个String类型,但是requiredType 传入的却是Integer类型,这时候就会触发这一步的操作,将String类型转换为Integer类型。

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

以上:内容部分参考
《Spring源码深度解析》
https://blog.csdn.net/andy_zhang2007/article/details/86514320
如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正

猜你喜欢

转载自blog.csdn.net/qq_36882793/article/details/105667530