Spring源码简读(一)之Bean对象的“前世今生”

Spring源码简读之Bean对象的“前世今生”

前言

本文旨在梳理Spring源码中IOC容器的创建以及Bean对象的创建流程和整理脉络,通过阅读源代码,了解Bean对象的“前世今生”,其中不过多赘述其中某些方法的具体实现,如感兴趣,可自行调试并阅读。

一、Spring容器和Bean对象的创建流程

Spring最重要的核心组件就是IOC,IOC的思想就是通过容器来管理Bean对象,IOC容器就像是一个生产产品的流水线上的机器,Spring创建出来的Bean就好像是流水线的终点生产出来的一个个精美绝伦的产品。通过对Spring源码的阅读,我将整个IOC容器的创建和Bean的加载过程可以通过下面的图来简单梳理。
![在这里插入图片描述](https://img-blog.csdnimg.cn/37778c371dc843ffaaf357710d0bf268.png
为了便于大家理解,现将图中的几个核心组件进行介绍

1.1核心组件

1.1.1 配置元信息

Spring IOC容器将对象实例的创建与对象实例的使用分离,当业务中需要依赖某个对象,不再依靠我们自己手动创建,只需向Spring要,Spring就会以注入的方式交给我们需要的依赖对象。既然将对象创建的任务交给了Spring,那么Spring就需要知道创建一个对象所需要的一些必要的信息。而这些必要的信息可以是Spring过去支持最完善的xml配置文件,或者是其他形式的例如properties的磁盘文件,也可以是现在主流的注解,甚至是直接的代码硬编码。总之,这些创建对象所需要的必要信息称为配置元信息。

1.2.1 BeanDefination

那么Spring是如何将这些配置文件中的配置元信息加载到内存中,来创建Bean对象的呢?BeanDefinition 是定义 Bean 的配置元信息接口,简单说就是对Bean信息的定义。描述一个bean的全部信息,比如他的class类型、Bean的作用域、是否懒加载等,Spring中每一个被扫描到的bean都会生成一个BeanDefinition,即配置元信息被加载到内存之后是以BeanDefination的形存在的即可。

1.3.1 BeanDefinationReader

Spring是如何看懂这些配置元信息的呢?这个就要靠我们的BeanDefinationReader了。不同的BeanDefinationReader拥有不同的功能,如果我们要读取xml配置元信息,那么可以使用XmlBeanDefinationReader。如果我们要读取properties配置文件,那么可以使用PropertiesBeanDefinitionReader加载。而如果我们要读取注解配置元信息,那么可以使用 AnnotatedBeanDefinitionReader加载。我们也可以很方便的自定义BeanDefinationReader来自己控制配置元信息的加载。总的来说,BeanDefinationReader的作用就是加载配置元信息,并将其转化为内存形式的BeanDefination。

1.4.1 BeanDefinationRegistory

Spring将存在于各处的配置元信息加载到内存,并转化为BeanDefination的形式后。当我们需要创建某一个对象实例的时候,找到相应的BeanDefination然后创建对象即可。那么我们需要某一个对象的时候,去哪里找到对应的BeanDefination呢?这种通过Bean定义的id找到对象的BeanDefination的对应关系或者说映射关系又是如何保存的呢?这就引出了BeanDefinationRegistry了。
Spring通过BeanDefinationReader将配置元信息加载到内存生成相应的BeanDefination之后,就将其注册到BeanDefinationRegistry中,BeanDefinationRegistry就是一个存放BeanDefination的大篮子,它也是一种键值对的形式,通过特定的Bean定义的id,映射到相应的BeanDefination。

1.5.1 BeanFactoryPostProcesser

BeanFactoryPostProcessor是容器启动阶段Spring提供的一个扩展点,主要负责对注册到BeanDefinationRegistry中的一个个的BeanDefination进行一定程度上的修改与替换。例如我们的配置元信息中有些可能会修改的配置信息散落到各处,不够灵活,修改相应配置的时候比较麻烦,这时我们可以使用占位符的方式来配置。

1.6.1 BeanFactory

既然是以Factory结尾,表示它是一个工厂类(接口), 它负责生产和管理bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等,其中XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系。XmlBeanFactory类将持有此XML配置元数据,并用它来构建一个完全可配置的系统或应用。

1.7.1 各种Aware接口

aware翻译的中文意思是意识到的,察觉到的。在Spring中有很多Aware接口,例如BeanNameAware,ApplicationContextAware等,它们的的作用有一个共同的目的就是,在Bean初始化的过程中来获取Spring的各种资源。当然,我们在对Spring进行扩展的时候也可以自定义Aware接口来实现Bean初始化的过程中对利用Spring容器的资源对Bean进行一些处理。

1.8.1 BeanPostProcesser

BeanPostProcesser接口也叫后置处理器,作用是在Bean对象在初始化的过程中,在显示调用初始化方法的前后添加我们自己的逻辑。我们在项目开发中可能经常会遇到对Bean对象初始化之前和之后做一些准备工作和收尾工作,常用的例如@PostContruct注解,就是在Bean初始化之前做一些处理,也就是通过后置处理器来进行操作的。

1.2 核心代码概览

相信看过Spring源码的朋友们对下面的方法肯定不会陌生,refresh方法是AbstractApplicationContext中的方法,也是IOC容器的最核心方法,通过它可以了解容器的创建和Bean加载的过程,大家可以通过代码中的注释,对流程有个大体的了解,感兴趣的话可以仔细阅读其中的每一个方法。这里只介绍每个方法的主要作用。

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// 准备刷新的上下文环境.
			// 刷新上下文环境,初始化上下文环境,对系统的环境便利或者系统属性进行准备和校验
			prepareRefresh();

			// 通知子类准备刷新的Bean工厂
			//获取新的beanFactory,销毁原有beanFactory、为每个bean生成BeanDefinition等
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 准备上下文中的Bean工厂
			// 对bean工厂的工作功能进行填充,配置工厂的标准上下文特征,例如上下文的ClassLoader和后处理器。
			prepareBeanFactory(beanFactory);

			try {
				//允许在上下文子类中对 bean 工厂进行后置处理。在beanfactory加载完成所有的bean后,想修改其中某个bean的定义,
				//或者对beanFactory做一些其他的配置,就可以在子类中对beanFactory进行后置处理(子类通过实现接口
				//BeanFactoryPostProcessor来自定义后置处理)。后置处理器执行的时间是:在所有的beanDenifition加载完成
				//之后,bean实例化之前执行。
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				
				// 触发上下文中的bean工厂的后置处理器
				invokeBeanFactoryPostProcessors(beanFactory);

				// 注册bean的后置处理器,对bean的创建进行拦截,并进行相应的处理
				// 实例化和注册beanFactory中扩展了BeanPostProcessor的bean。例如
				// AutowiredAnnotationBeanPostProcessor(处理被@Autowired注解修饰的bean并注入)
				// CommonAnnotationBeanPostProcessor(处理@PreDestroy、@PostConstruct、@Resource等多个注解的作用)等。
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// 初始化国际化工具类MessageSource。
				initMessageSource();

				// 初始化应用事件广播器。
				initApplicationEventMulticaster();

				// 这个方法在AbstractApplicationContext中没有实现,留给子类来初始化其他的Bean,
				//是个模板方法,在容器刷新的时候可以自定义逻辑(子类自己去实现逻辑),不同的Spring容器做不同的事情
				onRefresh();

				// 注册监听器,并且广播earlyApplicationEvents,也就是早期的事件
				registerListeners();

				// 初始化完剩下的单例(非懒加载的单例类)并调用BeanPostProcessors。
				//剩下的(非懒加载)单例Bean也就是我们自己定义的那些Bean,比如invokeBeanFactoryPostProcessors
				//方法中根据各种注解解析出来的类(扫描的@Bean之类的),在这个时候都会被初始化,
				//扫描的@Bean之类的,实例化的过程各种BeanPostProcessor开始起作用。
				finishBeanFactoryInitialization(beanFactory);

				// 通知生命周期处理器LifecycleProcessor完成刷新过程,同时发出ContextRefreshEvent通知别人
				finishRefresh();
			}
		}
	}

二、Bean对象加载的具体流程

经过第一章节的概括,相信大家对Spring的IOC容器和Bean对象的有了大致的了解,对Bean对象的生命周期有了进一步的了解,下面我将Spring的Bean对象的加载过程简单分为两个阶段,分别为解析注册BeanDefination阶段和Bean对象的创建阶段,本章以XML配置文件为例来详细介绍Bean的加载过程。

2.1 解析并注册BeanDefination

2.1.1 加载XML文件到XmlBeanFactory

首先,看一下XmlBeanFactory 的代码,如下:

public class XmlBeanFactory extends DefaultListableBeanFactory {

	private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);


	/**
	 * Create a new XmlBeanFactory with the given resource,
	 * which must be parsable using DOM.
	 * @param resource the XML resource to load bean definitions from
	 * @throws BeansException in case of loading or parsing errors
	 */
	public XmlBeanFactory(Resource resource) throws BeansException {
		this(resource, null);
	}

	/**
	 * Create a new XmlBeanFactory with the given input stream,
	 * which must be parsable using DOM.
	 * @param resource the XML resource to load bean definitions from
	 * @param parentBeanFactory parent bean factory
	 * @throws BeansException in case of loading or parsing errors
	 */
	public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
		super(parentBeanFactory);
		this.reader.loadBeanDefinitions(resource);
	}

}

其XmlBeanFactory继承了DefaultListableBeanFactory,而DefaultListableBeanFactory为整个Bean加载的核心部分,是Spring注册及加载bean的默认实现,而不同的是XmlBeanFactory使用的自定义的XmlBeanDefinitionReader来读取BeanDefinition,其中参数Resource接口抽象了所有Spring内部使用到的底层资源:File,URL,Classpath等。

2.1.2 解析并注册BeanDefinition

XmlBeanFactory中最重要的方法就是this.reader.loadBeanDefinitions(resource),即加载BeanDefinition,我们跟进代码就可以找到里面最重要的方法,如下图

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {

		try {
			//将资源文件解析为Document
			Document doc = doLoadDocument(inputSource, resource);
			//解析及注册BeanDefinations
			int count = registerBeanDefinitions(doc, resource);
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + count + " bean definitions from " + resource);
			}
			return count;
		}
		catch (BeanDefinitionStoreException ex) {
			throw ex;
		}
		catch (SAXParseException ex) {
			throw new XmlBeanDefinitionStoreException(resource.getDescription(),
					"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
		}
		catch (SAXException ex) {
			throw new XmlBeanDefinitionStoreException(resource.getDescription(),
					"XML document from " + resource + " is invalid", ex);
		}
		catch (ParserConfigurationException ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"Parser configuration exception parsing XML from " + resource, ex);
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"IOException parsing XML document from " + resource, ex);
		}
		catch (Throwable ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"Unexpected exception parsing XML document from " + resource, ex);
		}
	}

其中,doLoadDocument(inputSource, resource);和registerBeanDefinitions(doc, resource)分别获取Document对象和解析并注册BeanDefinitions。解析和注册bean的过程中首先会调用doRegisterBeanDefinitions,这其中用到了模版方法的设计模式,preProcessXml和postProcessXml为模版方法的扩展接口,解析BeanDefiniton的工作都在parseBeanDefinitions方法中。

protected void doRegisterBeanDefinitions(Element root) {
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);

		if (this.delegate.isDefaultNamespace(root)) {
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			if (StringUtils.hasText(profileSpec)) {
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
					if (logger.isDebugEnabled()) {
						logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
								"] not matching: " + getReaderContext().getResource());
					}
					return;
				}
			}
		}
		//模版方法
		preProcessXml(root);
		//解析BeanDefinition
		parseBeanDefinitions(root, this.delegate);
		//模版方法
		postProcessXml(root);

		this.delegate = parent;
	}

进入到parseBeanDefinition方法中,可以看到就是简单的对Document元素进行了解析,通过委派给BeanDefinitionParserDelegate来进行元素的解析,可以在BeanDefinitionParserDelegate中看到Bean的属性。

	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
					    //注册BeanDefinition
						parseDefaultElement(ele, delegate);
					}
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}
public class BeanDefinitionParserDelegate {

	public static final String BEANS_NAMESPACE_URI = "http://www.springframework.org/schema/beans";

	public static final String MULTI_VALUE_ATTRIBUTE_DELIMITERS = ",; ";

	/**
	 * Value of a T/F attribute that represents true.
	 * Anything else represents false.
	 */
	public static final String TRUE_VALUE = "true";

	public static final String FALSE_VALUE = "false";

	public static final String DEFAULT_VALUE = "default";

	public static final String DESCRIPTION_ELEMENT = "description";

	public static final String AUTOWIRE_NO_VALUE = "no";

	public static final String AUTOWIRE_BY_NAME_VALUE = "byName";

	public static final String AUTOWIRE_BY_TYPE_VALUE = "byType";

	public static final String AUTOWIRE_CONSTRUCTOR_VALUE = "constructor";

	public static final String AUTOWIRE_AUTODETECT_VALUE = "autodetect";

	public static final String NAME_ATTRIBUTE = "name";

	public static final String BEAN_ELEMENT = "bean";

	public static final String META_ELEMENT = "meta";

	public static final String ID_ATTRIBUTE = "id";

	public static final String PARENT_ATTRIBUTE = "parent";

	public static final String CLASS_ATTRIBUTE = "class";

	public static final String ABSTRACT_ATTRIBUTE = "abstract";

	public static final String SCOPE_ATTRIBUTE = "scope";

	private static final String SINGLETON_ATTRIBUTE = "singleton";

	public static final String LAZY_INIT_ATTRIBUTE = "lazy-init";

	public static final String AUTOWIRE_ATTRIBUTE = "autowire";

	public static final String AUTOWIRE_CANDIDATE_ATTRIBUTE = "autowire-candidate";

	public static final String PRIMARY_ATTRIBUTE = "primary";

	public static final String DEPENDS_ON_ATTRIBUTE = "depends-on";

	public static final String INIT_METHOD_ATTRIBUTE = "init-method";

	public static final String DESTROY_METHOD_ATTRIBUTE = "destroy-method";

	public static final String FACTORY_METHOD_ATTRIBUTE = "factory-method";
	}


至此,BeanDefinition已经从Document对象解析完毕,接下来就是以beanName为key注册到map里,我们继续看代码,上面提到的parseBeanDefinitions方法中最重要的方法为parseDefaultElement(ele, delegate),而它其中的BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())方法则是真正注册BeanDefinition的最终实现。

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		//通过bean标签来获取注册bean
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}
	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}

最终,会统一注册到最开始提到的Spring核心容器DefaultListableBeanFactory中的private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);里。至此,BeanDefinition完成了解析和注册。

2.2 Bean对象的创建

容器启动后,BeanDefination已经解析并注册到Spring核心容器DefaultListableBeanFactory中,接下来就应该获取Bean对象,完成Bean对象的加载。因此,我们可以看一下getBean方法。DefaultListableBeanFactory继承DefaultListableBeanFactory类,然后DefaultListableBeanFactory类继承AbstractBeanFactory类,AbstractBeanFactory类中的getBean方法则是获取bean对象的核心方法。
同样,我也可以在第一章介绍的refresh方法中的finishBeanFactoryInitialization(beanFactory);中找到对getBean方法的调用,意味着在完成BeanFactory初始化的最后,会将Bean对象注入到BeanFactory中,完成Bean对象的加载。具体方法跟进如下:

在这里插入图片描述
在这里插入图片描述
上面方法中可以清楚的看到,从BeanDefination到Bean的转化,感兴趣的朋友们可以跟进代码详细查看。上图的getBean方法即是AbstractBeanFactory的getBean方法,而其中的doGetBean()方法的总体功能就是在创建bean对象之前,先去缓存或者beanFactory工厂中查看是否存在bean,如果存在,则返回,不存在,则进行对应的创建流程。下面我们详细分析一下doGetBean()方法,感兴趣的可以仔细阅读注释。

public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
			throws BeansException {

		return doGetBean(name, requiredType, args, false);
	}

	@SuppressWarnings("unchecked")
	protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
		
		//提取对应的beanName
		String beanName = transformedBeanName(name);
		Object beanInstance;

		// 检查缓存中或者实例工厂中是否有对应的实例
		//为什么会使用这段代码呢?
		//因为在创建单里bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖
		//Spring创建bean的原则是不等bean创建完成就会将bean的ObjectFactory提早曝光
		//也就是将ObjectFactory加入到缓存中,一旦下一个bean创建的时候需要依赖上个bean则直接使用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 + "'");
				}
			}
			//返回对应的实例
			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// 只有在单例模式下才会尝试解决循环依赖
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// 查看beanDefination是否存在
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// 如果beanDefinationMap中不存在,则尝试从parentBeanFactory中检测
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
					.tag("beanName", name);
			try {
				if (requiredType != null) {
					beanCreation.tag("beanType", requiredType::toString);
				}
				//将存储在xml配置文件的GernericBeanDefinition转换成RootBeanDefinition
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

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

				// 创建bean实例
				if (mbd.isSingleton()) {
				 //重要的事情说三遍
		         //获取单例Bean对象
		         //获取单例Bean对象
		         //获取单例Bean对象
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							destroySingleton(beanName);
							throw ex;
						}
					});
					beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				else if (mbd.isPrototype()) {
					// 原型模式bean创建
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					String scopeName = mbd.getScope();
					if (!StringUtils.hasLength(scopeName)) {
						throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
					}
					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);
							}
						});
						beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new ScopeNotActiveException(beanName, scopeName, ex);
					}
				}
			}
			catch (BeansException ex) {
				beanCreation.tag("exception", ex.getClass().toString());
				beanCreation.tag("message", String.valueOf(ex.getMessage()));
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
			finally {
				beanCreation.end();
			}
		}

		return adaptBeanInstance(name, beanInstance, requiredType);
	}

至此,Bean对象的加载已经基本完成,在使用的时候可以通过getBean方法来获取IOC容器中的Bean对象,那么可能有人会疑问,那Bean对象加载完之后,到底存储在哪里呢?起初在我没看到源码之前,我的思路在Bean对象加载完成之后,即Bean对象初始化后可能会将Bean对象存储到某种缓存里,参考BeanDefination的思想,我猜Bean对象同样应该存储到ConcurrenHashMap里。而且该动作应该就是doCreateBean里,初始化完成之后,将Bean对象添加到ConcurrenHashMap里。带着我的猜想,我跟进了上图中的 getSingleton方法,方法顾名思义获取单例Bean对象,而真正的目的是从缓存中获取单例bean,通过回调函数也可以看到,createBean方法是创建Bean对象的意思,因此进入getSingleton如下:

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) {
		    // 从缓存池中获取bean:singletonObjects 一级缓
			Object singletonObject = this.singletonObjects.get(beanName)// 如果一级缓存中为null
			if (singletonObject == null) {
			    //初始化前操作,校验是否 beanName 是否有别的线程在初始化,并记录beanName的初始化状态
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
				   // 调用createBean方法实例化bean
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
				    //初始化后的操作,移除初始化状态
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					//重要的事情说三遍
					// 注册单例Bean到缓存
					// 注册单例Bean到缓存
					// 注册单例Bean到缓存
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

该方法返回在给定名称下注册的(原始)单例对象,如果还没有注册,则通过回调函数createBean创建并注册一个新的单例对象。具体的执行步骤如下:
(1)检查缓存是否已经加载过
(2)没有加载,则记录beanName 的加载状态
(3)调用createBean()方法实例化 bean
(4)bean实例化完成之后,移除初始化状态
(5)将实例化结果记录到缓存并删除加载 bean 过程中所记录到的各种辅助状态
那么创建Bean对象和注册Bean对象的操作都在这个方法里,仔细阅读源码,发现addSingleton(beanName, singletonObject)就是我们要找的方法,请看下面代码:

	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			// 将Bean对象存储到singletonObjects集合中
			this.singletonObjects.put(beanName, singletonObject);
			// 移除工厂方法
			this.singletonFactories.remove(beanName);
			// 从早期单例对象集合中移除
			this.earlySingletonObjects.remove(beanName);
			// 注册单例对象名称
			this.registeredSingletons.add(beanName);
		}
	}

上面的代码,非常简单易懂,singletonObjects就是我前面猜想的ConcurrentHashMap集合,用来缓存单例Bean对象的。earlySingletonObjects 变量,它也是单例缓存,也是用来保存 beanName 和 创建 bean 实例之间的关系。与 singletonFactories 不同的是,当一个单例 bean 被放入到这 early 单例缓存后,就要从 singletonFactories 中移除,两者是互斥的,主要用来解决循环依赖的问题。
当Bean的作用域为单例时,第一次初始化后的Bean对象会被存储到singletonObjects里,再次使用的时候直接从缓存里获取即可。最后,我们再看看当缓存中没有Bean对象时,Bean对象是如何创建的,请看createBean方法。

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

		if (logger.isTraceEnabled()) {
			logger.trace("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;
		// 确保此时bean类已经被解析,并且克隆 bean 定义,以防动态解析的类不能存储在共享合并 bean 定义中。
	    // 锁定 class,根据设置的 class 属性或者根据 className 来解析 Class
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// 验证及准备重写的方法
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// 解析指定bean,让 beanPostProcessor 有机会返回代理而不是目标bean实例。
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			// 短路操作,如果代理成功创建 bean 后,直接返回
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
			//重要的事情说三遍
		    //创建Bean对象
		    //创建Bean对象
		    //创建Bean对象
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}

上面这段代码的执行流程如下:
(1)根据设置的 class 属性或者根据 className 来解析 Class
(2)验证及准备覆盖的方法 这个方法是用来处理以下两个配置的:我们在解析默认标签时,会识别 lookup-method 和 replaced-method 属性,然后这两个配置的加载将会统一存放在 beanDefinition 中的 methodOverrides 属性里。
(3)应用初始化前的后处理器,解析指定 bean 是否存在初始化前的短路操作
(4)创建 bean
正如上段代码所示,createBean方法中的doCreateBean方法应该是真正创建Bean对象的方法,我们话不多说,继续跟进,一探究竟。

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

		// 实例化Bean
		BeanWrapper instanceWrapper = null;
		// 如果bean是单例,就先清除缓存中的bean信息
		if (mbd.isSingleton()) {
			// 根据指定bean使用对应的策略实例化bean,例如:工厂方法,构造函数自动注入,简单初始化
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// 允许后置处理器修改合并的BeanDefinition.
		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;
			}
		}

		//快速缓存单例以解析循环引用
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			//第二个参数是回调接口,实现的功能是将切面动态织入 bean
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// 初始化bean
		Object exposedObject = bean;
		try {
		   // 对 bean 进行填充,将各个属性值注入
           // 如果存在对其它 bean 的依赖,将会递归初始化依赖的 bean
			populateBean(beanName, mbd, instanceWrapper);
			// 调用初始化方法,例如 init-method
			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);
			// earlySingletonReference 只有在检测到有循环依赖的情况下才 不为空
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
				   // 如果 exposedObject 没有在初始化方法中被改变,也就是没有被增强
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					// bean 创建后,它所依赖的 bean 一定是已经创建了
				    // 在上面已经找到它有依赖的 bean,如果 actualDependentBeans 不为空
				    // 表示还有依赖的 bean 没有初始化完成,也就是存在循环依赖
					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 " +
								"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// 注册销毁bean对象
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

通过注释可以简单的看到上面的方法中完成了bean的创建、初始化和最后的销毁,加载bean对象最终的操作就在此方法完成。

最后,通过上面对源码的跟踪和简单讲解,我们基本上了解了Bean对象的创建过程。

三、总结

本文第一章通过介绍refresh方法,简单讲解了整个IOC容器的创建过程,而第二章则是真正的通过讲解源代码介绍了Bean对象的加载过程,即如何从xml文件变成了Bean对象,并注入到了IOC容器中,至此,Spring中最核心的组件IOC容器和它所管理的Bean对象就介绍到这里。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值