Spring源码阅读(一)浅谈beanFactory加载bean

题外话:学java 就要看源码,为什么要看源码?可以从中学到各位大佬的思想啊,看看大佬们是怎么写代码的?哈哈,谁TM想看源码啊,还不是被逼的!!!因为要打怪升级啊!@#¥%……&*

说重点,这篇文章分析下我们熟悉的优秀springFramework框架是怎么加载bean和管理bean的~
————————————————
在开始之前,先看一下这篇文章大概会涉及到的内容,如有不清晰的地方后续补充完善,我用思维导图展示一下
在这里插入图片描述

引入案例

  首先,我们我们知道spring加载bean有两种方式,一种是通过beanFactory类,另外一种是我们常用的ApplicationContext,我们先以基本的BeanFactory来获取bean。

定义一个bean类

public class Person {
	private String name = "wuxiaojun";
	private int age ;
	//省略get/set...
	}

定义资源文件 beanFactoryTest.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
                      https://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<bean id="person" class="org.springframework.wmj.Person" />
</beans>

测试类MyBeanFactoryTest.java

@SuppressWarnings("deprecation")
public class MyBeanFactoryTest {
	@Test
	public void testSimpleLoad() {
		//1、beanFactory
		BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(
			"wmjbeans/beanFactoryTest.xml"));
		Person person = (Person) beanFactory.getBean("person");
		assertEquals("wuxiaojun", person.getName());
		System.out.println("beanFactory===>"+person.getName());	

	    /*
	    //2、ApplicationContext
	    ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
				"wmjbeans/beanFactoryTest.xml");
		Person person = (Person) ctx.getBean("person");
		assertEquals("wuxiaojun", person.getName());
		System.out.println("ClassPathXmlApplicationContext===>"+person.getName());
		*/
	}
}

一、第一部分

Spring加载bean是一个相当复杂的过程,这里我把它拆分两个部分,分别从加载配置到内存中,和加载Bean两个部分进行讲起。

1、读取配置文件

  执行上面案列中testSimpleLoad方法,spring就两句代码,具体干了什么事?我们不妨先通过时序图,通过整体来把控全局,或许稍微容易理解一些(可能第一遍完全看不懂,结合代码多看几遍),我们从new XmlBeanFactory说起,下面是该过程执行的时序图:
在这里插入图片描述
  Spring核心都在定义的xml文件中,首先肯定要拿到对应的xml资源文件new ClassPathResource(“beanFactoryTest.xml”)得到resource对象。跟踪进去看看代码里面写了什么

public XmlBeanFactory(Resource resource) throws BeansException {
		//调用自身构造函数
		this(resource, null);
	}
	
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
		//再次调用父类构造函数
		super(parentBeanFactory);
		this.reader.loadBeanDefinitions(resource);
	}

  主要做一件事,就是通过资源文件来加载BeanDefinitions,在这里我们看见上图中的loadBeanDefinitions了,下面再结合时序图看看XmlBeanDefinitionReader类中loadBeanDefinitions具体做了什么
在这里插入图片描述
通过图我们知道,方法最终目的是为了得到BeanDefinition,我们结合下面代码

@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
	    //对resource进行编码,通过返回编码后的resource对象
		return loadBeanDefinitions(new EncodedResource(resource));
        }
	
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isTraceEnabled()) {
			logger.trace("Loading XML bean definitions from " + encodedResource);
		}

		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
		if (currentResources == null) {
			currentResources = new HashSet<>(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}
		try {
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				inputStream.close();
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}

  代码逻辑还算清晰,首先对resource进行编码,然后将编码后的encodedResource作为参数继续调用loadBeanDefinitions(EncodedResource encodedResource),在这个方法里,忽略异常捕获信息的话,只做了一件事,就是通过encodedResource获取资源inputStrea,根据inputStrea得到inputSource,如果有主动对encodedResource有设置编码的话,就是用我们设置的编码。但是很遗憾,并没有我们想要看的结果,最终通过doLoadBeanDefinitions方法干活去了~

看看doLoadBeanDefinitions做了什么事

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
		try {
			//根据资源文件获取xml的document文档
			Document doc = doLoadDocument(inputSource, resource);
			//注册BeanDefinitions,返回注册成功的definitions个数
			int count = registerBeanDefinitions(doc, resource);
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + count + " bean definitions from " + resource);
			}
			return count;
		}catch{
		//省略异常捕获信息...
		}
	}

  是的,这个方法又没干活,只讲具体的干活的分派给另外两个方法,结合我的注释应该很好理解,下面来我们逐一分析,先看doLoadDocument(inputSource, resource)如何加载doc的

2、获取Document对象

直接进入doLoadDocument()方法

/**
	 * Actually load the specified document using the configured DocumentLoader.
	 * @param inputSource the SAX InputSource to read from
	 * @param resource the resource descriptor for the XML file
	 * @return the DOM Document
	 * @throws Exception when thrown from the DocumentLoader
	 * @see #setDocumentLoader
	 * @see DocumentLoader#loadDocument
	 */
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
		return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
				getValidationModeForResource(resource), isNamespaceAware());
	}

  该方法中有两点要注意,首先是通过 getEntityResolver() 获取到参数EntityResolver,何为EntitiResolver?官网这样解释:如果SAX应用程序需要实现自定义处理外部实体,则必须实现此接口并使用setEntityResolver方法向SAX驱动器注册一个实例。也就是说,对于解析一个XML,SAX首先读取该XML文档上的声明,根据声明去寻找相应的DTD定义,以便对文档进行一个验证。默认的寻找规则,即通过网络(实现上就是声明的DTD的URL地址)来下载相应的DTD声明,并进行认证。下载的过程漫长,而且当网络中断或不可用的时候,这里会报错,就是因为相应的DTD声明没有被找到的原因。
  因为本编具体只分析Spring-bean相关内容,这里暂不具体分析XML文档结构相关知识,在这我们只要知道定义一个XML有DTD和XSD两种声明方式就ok了,可以了解下DTD和XSD相关知识。
  其次,getValidationModeForResource(resource) 就是用来获取XML的验证模式的,具体如何获取,是通过读取XML文件,查看XML内容中是否包含XSD或者DTD来判断XML的验证模式,这部分代码比较简单,就不贴了

我们具体看看document是如何被加载的,跟踪到DefaultDocumentLoader类中去

   /**
	 * Load the {@link Document} at the supplied {@link InputSource} using the standard JAXP-configured
	 * XML parser.
	 */
	@Override
	public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
			ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
		DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
		if (logger.isTraceEnabled()) {
			logger.trace("Using JAXP provider [" + factory.getClass().getName() + "]");
		}
		DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
		return builder.parse(inputSource);
	}

  这里并没有特别之处,Spring首先创建DocumentBuilderFactory,再通过DocumentBuilderFactory创建DocumentBuilder,进而解析inputSource来返回Document对象。

3、注册BeanDefinition

  得到document对象后,我们就可以根据document来获取注册BeanDefinitions了,我们再次回到registerBeanDefinitions(doc, resource)方法中

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		//通过反射创建一个documentReader实例
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		//获取注册前的BeanDefinition个数
		int countBefore = getRegistry().getBeanDefinitionCount();
		//注册BeanDefinition
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		//返回此次注册的BeanDefinition的个数
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

  这个方法很简单,根据注释也都能看明白,我们主要看看第三步注册BeanDefinition,
BeanDefinitionDocumentReader 是个接口,其子类实现在DefaultBeanDefinitionDocumentReader类中,在这个类中我们来寻找答案

   @Override
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		doRegisterBeanDefinitions(doc.getDocumentElement());
	}
	
    @SuppressWarnings("deprecation")  // for Environment.acceptsProfiles(String...)
	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);
		parseBeanDefinitions(root, this.delegate);
		//注册后置处理
		postProcessXml(root);

		this.delegate = parent;
	}

  一大段代码,我们只关心的只有最后面三行,前面一大串是Spring对Profile的支持,Profile是Spring用来针对不同环境对不同的配置提供支持的,这里不具体分析,大家可以谷歌一下“profile配置”了解。
  看了源码发现preProcessXml(root);和postProcessXml(root);这两句方法里面是空的,什么也没有,有人认为这是多余的两句代码,其实不然。这里正是体现Spring作为一个开放式架构的优秀之处,他可以提供给开发者自由的拓展功能,在有必要的时候继承DefaultBeanDefinitionDocumentReader类,重写这两个方法,提供我们自定义的功能。

我们看看核心方法 parseBeanDefinitions(root, this.delegate)

    /**
	 * Parse the elements at the root level in the document:
	 * "import", "alias", "bean".
	 * @param root the DOM root element of the document
	 */
	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)) {
						//解析默认标签
						parseDefaultElement(ele, delegate);
					}
					else {
						//解析自定义标签
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			//解析自定义标签
			delegate.parseCustomElement(root);
		}
	}

  在Spring的配置文件中,有我们常见的一些标签,比如:import、alias、bean、beans,再或者如果我们使用了自己定义的一别标签,比如:s:person、s:age、s:name,当然使用自定义标签时,需要在xml文档中加上我们自己的命名空间。

这个方法里,就是对Spring使用到的标签的解析,我们就看默认标签的解析

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);//解析import标签
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);//解析alias标签
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);//解析bean标签
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			doRegisterBeanDefinitions(ele);//解析beans标签
		}
	}

  默认标签的解析分为import、alias、bean、beans;对于beans标签及配置文件的最高父标签,采用深度优先遍历的方式,再次进入parseBeanDefinitions方法中进入解析。

这里只分析较为复杂的bean标签的解析,其他的标签类似

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		// 对bean标签的默认属性和子标签进行处理,将其封装为一个BeanDefinition对象,并放入BeanDefinitionHolder中
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
		    // 进行自定义属性或自定义子标签的装饰
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// 注册当前的BeanDefinition
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			 // 调用注册了bean标签解析完成的事件处理逻辑
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

这里我们直接进入BeanDefinitionParserDelegate.decorateBeanDefinitionIfRequired()方法中:

public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
			Element ele, BeanDefinitionHolder definitionHolder, @Nullable BeanDefinition containingBd) {

		BeanDefinitionHolder finalDefinition = definitionHolder;
		// 处理自定义属性
		NamedNodeMap attributes = ele.getAttributes();
		for (int i = 0; i < attributes.getLength(); i++) {
			Node node = attributes.item(i);
			finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
		}
		// 处理自定义子标签
		NodeList children = ele.getChildNodes();
		for (int i = 0; i < children.getLength(); i++) {
			Node node = children.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
			}
		}
		return finalDefinition;
	}

可以看到,自定义属性和自定义子标签的解析都是通过decorateIfRequired()方法进行的,如下是该方法的定义:

public BeanDefinitionHolder decorateIfRequired(
			Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
        // 获取当前自定义属性或子标签的命名空间url
		String namespaceUri = getNamespaceURI(node);
		// 判断其如果为spring默认的命名空间则不对其进行处理
		if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) {
			// 获取当前命名空间对应的NamespaceHandler对象
			NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
			if (handler != null) {
				// 对当前的BeanDefinitionHolder进行装饰
				BeanDefinitionHolder decorated =
						handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
				if (decorated != null) {
					return decorated;
				}
			}
			else if (namespaceUri.startsWith("http://www.springframework.org/schema/")) {
				error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
			}
			else {
				// A custom namespace, not to be handled by Spring - maybe "xml:...".
				if (logger.isDebugEnabled()) {
					logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
				}
			}
		}
		return originalDef;
	}

  decorateIfRequired()方法首先会获取当前自定义属性或子标签对应的命名空间url,然后根据该url获取当前命名空间对应的NamespaceHandler处理逻辑,并且调用其decorate()方法进行装饰,如下是该方法的实现:

	@Nullable
	public BeanDefinitionHolder decorate(
			Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
		// 获取当前自定义属性或子标签注册的BeanDefinitionDecorator对象
		BeanDefinitionDecorator decorator = findDecoratorForNode(node, parserContext);
		// 调用自定义的BeanDefinitionDecorator.decorate()方法进行装饰
		return (decorator != null ? decorator.decorate(node, definition, parserContext) : null);
	}

如下是findDecoratorForNode()的实现

@Nullable
	private BeanDefinitionDecorator findDecoratorForNode(Node node, ParserContext parserContext) {
		BeanDefinitionDecorator decorator = null;
		// 获取当前标签或属性的局部键名
		String localName = parserContext.getDelegate().getLocalName(node);
		 // 判断当前节点是属性还是子标签,根据情况不同获取不同的Decorator处理逻辑
		if (node instanceof Element) {
			decorator = this.decorators.get(localName);
		}
		else if (node instanceof Attr) {
			decorator = this.attributeDecorators.get(localName);
		}
		else {
			parserContext.getReaderContext().fatal(
					"Cannot decorate based on Nodes of type [" + node.getClass().getName() + "]", node);
		}
		if (decorator == null) {
			parserContext.getReaderContext().fatal("Cannot locate BeanDefinitionDecorator for " +
					(node instanceof Element ? "element" : "attribute") + " [" + localName + "]", node);
		}
		return decorator;
	}

  对于BeanDefinitionDecorator处理逻辑的查找,可以看到,其会根据节点的类型进行判断,根据不同的情况获取不同的BeanDefinitionDecorator处理对象。
  历经千辛万苦,我们终于封装了一个BeanDefinition对象,接下来回到上文中的processBeanDefinition()方法中可以注册BeanDefinition了,下来就好理解了,注册完成通知解析完成的事件处理监听器发出通知。

分析了这么多,我们先来小结一下,以上过程中,无非分为三个阶段

1. 读取配置文件
2. 获取xml的验证模式,并根据验证模式得到document文档对象
3. 解析spring标签,注册beanDefinition

是的,以上只是完成了基本的资源文件的读取,和beanDefinition的注册,也就是执行完new XmlBeanFactory("resource”)后Spring干的事。

二、第二部分

  这里开始,将要进入重点bean的加载部分,即代码 Person person = (Person) beanFactory.getBean(“person”) 的逻辑…你,准备好了吗!!

好了,直接上代码

AbstractBeanFactory.java

	//---------------------------------------------------------------------
	// Implementation of BeanFactory interface
	//---------------------------------------------------------------------
    
    @Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}
	
   /**
	 * Return an instance, which may be shared or independent, of the specified bean.
	 * @param name the name of the bean to retrieve
	 * @param requiredType the required type of the bean to retrieve
	 * @param args arguments to use when creating a bean instance using explicit arguments
	 * (only applied when creating a new instance as opposed to retrieving an existing one)
	 * @param typeCheckOnly whether the instance is obtained for a type check,
	 * not for actual use
	 * @return an instance of the bean
	 * @throws BeansException if the bean could not be created
	 */
	@SuppressWarnings("unchecked")
	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、尝试从缓存中加载单例
		Object sharedInstance = getSingleton(beanName);
		//3、得到 bean 的实例 beanInstance
		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 + "'");
				}
			}
			//返回对应的实例,有时候存在诸如BeanFactory的情况并不是直接返回实例本身而是返回指定方法返回的实例
			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.
			//5、检测parentBeanFactory
			BeanFactory parentBeanFactory = getParentBeanFactory();
			//如果BeanDefinitionMap中也就是已经加载的类中不包括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);
				}
				//递归到BeanFactory中寻找
				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、转换成RootBeanDefinition
			    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则需要递归实例化依赖的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
				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);
				}
				// 原型 bean(new一个)
				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类型的bean(Request、Session、Global session)
				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;
	}

  不看不知道,一看 原来Spring就一句getBean,就做了这么多事!~
结合我的注释,可以将上面加载bean的逻辑大概划分为9个步骤,下面依次来讲下这9个小步骤。
  老规矩,代码太多,容易绕晕,我们还是先从整体来把握,来明确我们最后想要的结果。我们先来看下整个getBean的逻辑时序图。

bean的获取过程
结合时序图,再一步一步分析代码。

1、 转换对应beanName

  也许有人不理解对应的beanName是什么意思,传入参数name不就是beanName吗?其实不是,这里传入参数name也有可能是别名,也有可能是FactoryBean,所以需要一系列的解析。解析如下:

//AbstractBeanFactory.java
protected String transformedBeanName(String name) {
		return canonicalName(BeanFactoryUtils.transformedBeanName(name));
	}	
/*
BeanFactoryUtils.java
去除BeanFactory修饰符,也就是如果name=“&aa”,首先去除& 而使name=“aa”
*/
public static String transformedBeanName(String name) {
		Assert.notNull(name, "'name' must not be null");
		if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
			return name;
		}
		return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
			do {
				beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
			}
			while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
			return beanName;
		});
	}	
/*
SimpleAliasRegistry.java
取指定的alias所表示的最终beanName,如别名A指向B的bean,则返回B,若别名A指向别名B,别名B又指向C的bean,则返回C
*/
public String canonicalName(String name) {
		String canonicalName = name;
		// Handle aliasing...
		String resolvedName;
		do {
			resolvedName = this.aliasMap.get(canonicalName);
			if (resolvedName != null) {
				canonicalName = resolvedName;
			}
		}
		while (resolvedName != null);
		return canonicalName;
	}

2、从缓存中加载单例

  单例在Spring同一个容器中只会被创建一次,后续再获取bean,就直接从单例缓存中获取。这里也是尝试加载,如果加载不成功再次尝试从singletonFactories中加载。因为在创建单列bean的时候会存在依赖注入,而在创建依赖的时候为了避免循环依赖,在Spring中创建bean的原则是不等bean创建完就会将创建的bean的ObjectFactory提早曝光到缓存中,一旦下一个bean创建的时候需要依赖上一个bean则直接使用ObjectFactory。(这里涉及到循环依赖相关的知识点,有空我也整理一下相关知识)

//DefaultSingletonBeanRegistry.java
@Override
@Nullable
public Object getSingleton(String beanName) {
	return getSingleton(beanName, true);
}
	
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	Object singletonObject = this.singletonObjects.get(beanName);
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		synchronized (this.singletonObjects) {
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return singletonObject;
}

  这里因为涉及到循环依赖的检测,会涉及到许多变量的存储。先解释一下方法的大概内容,首先尝试从singletonObjects里获取实例,获取不到的话再从earlySingletonObjects里获取,如果还是获取不到,在尝试从singletonFactories里面获取beanName对应的ObjectFactory,然后再调用ObjectFactory的getObject来创建bean,并放到earlySingletonObjects里面去,同时从singletonFactories里面remove掉这个ObjectFactory。

这里涉及到存储bean的不同map,可能有点崩溃,大致各map存放的bean如下:

  • singletonObjects:保存BeanName和创建bean实例之间的关系,ben name–>bean instance
  • singletonFactories:保存beanName和创建bean工厂之间的关系,ben name–>ObjectFactory
  • earlySingletonObjects:也是保存beanName和创建bean实例之间的关系,与>singletonObjects不同在于,当一个单例bean被放到这里面之后,那么当bean还在创建>过程中,就可以通过getBean方法获取到了,其目的是用来检测循环依赖。
  • registeredSingletons:用来保存当前所有已注册的bean

3、bean的实例化

  如果从缓存中得到bean的原始状态,则需要对bean进行实例化。这里说明一下,缓存中记录的只是原始bean的状态,并不是我们最终想要的bean。例如我们需要对工厂bean进行处理,那么这里得到的其实是工厂bean的初始状态,但是我们真正需要的是工厂bean中定义的factory-method方法中返回的bean。
  也就是说,我们得到bean的实例后要做的第一件事就是调用这个方法来检测一下正确性,其实就是检测当前的bean是否是FactoryBean类型的bean,如果是,那么就该调用对应的FactoryBean实例中的getObject()作为返回值。而getObjectForBeanInstance就是完成这个工作的。

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.
		//若name是工厂相关(以&为前缀)
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			//且又不是FactoryBean类型,则校验不通过
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
		}
		//现在我们有了bean实例,这个实例可能是正常的bean或者是FactoryBean
		//如果是FactoryBean,我们使用它创建实例,
		//但如果用户想要直接获取工厂实例而不是工厂的getObject方法对应的实例,那么传入的name应该加前缀&
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}
		//加载FactoryBean
		Object object = null;
		if (mbd == null) {
			//先尝试从缓存中加载
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// 经过上面判断我们知道这个beanInstance一定是FactoryBean类型
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			if (mbd == null && containsBeanDefinition(beanName)) {
				//将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition
				//如果指定beanName是子bean的话同时合并父类相关的属性
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			//是否用户定义的而不是程序本身定义的
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

我们梳理一下上面代码:

1)对FactoryBean正确性进行验证
2)对非FactoryBean不做任何处理
3)对bean进行转换
4)将从Factory中解析bean的工作委托给 getObjectFromFactoryBean方法了

这就是上面代码的逻辑,无非是多了一些辅助判断,下面我们看看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);
					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;
							}
							//标记singletonBean正在创建中
							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 {
								//将标记singletonBean正在创建中的状态移除
								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;
		}
	}

  在这个方法里,我们还是没有看到想要的代码,这里似乎只做了一件事如果返回的bean是单例,就要保证全局唯一,同时也因为单例,不必重复加载,可以使用缓存来提高性能,就是将加载过的bean放进缓存,方便下次调用。我们到委托的doGetObjectFromFactoryBean方法里去看看

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

  这里我们终于看到那句代码 object = factory.getObject(); 是的,就是它。
  讲到这里,有点需要注意下,在getObjectFromFactoryBean方法中,当执行完object = doGetObjectFromFactoryBean(factory, beanName);后,就已经得到我们想要的结果了,那下面还有一大串代码是干嘛的,通过注释我们知道是对ObjectFactory的后处理器,对于Spring的后处理器,大概意思是在Spring获取bean后,尽可能的保证初始化后都会调用注册的BeanPostProcessor的postProcessAfterInitialization方法进行处理,在实际的开发中我们可以针对此对自己的特殊业务进行设计,这不也即就是Spring的高明之处吗,说他是可扩展的优秀框架也不为过!(面向对象的设计)

4、原型模式的依赖检查

  只有在单例情况下才会尝试解决循环依赖,如果A中有B的属性,B中有A的属性,那么当依赖注入的时候,会产生当A还未创建完成的时候因为对于B的创建再次返回创建A造成循环依赖,也就是isPrototypeCurrentlyInCreation(beanName)的判断为true。

这里会涉及到Spring中循环依赖的知识点,对于循环依赖,Spring分以下两种情况

  1. 构造器循环依赖,这种依赖是无法解决的,只能通过抛出异常来处理
  2. setter循环依赖,可以处理

当然,对依赖的处理只是限于单例的情况下,对原型模式的bean,spring是无法解决的,所以才有了这一步骤,对原型模式的依赖检查。

5、检测parentBeanFactory

从代码上看,如果缓存中没有数据的话,直接转到父类工厂上去加载,这是为什么呢?
看看判断条件:parentBeanFactory != null && !containsBeanDefinition(beanName)。parentBeanFactory 为空,则其他都是浮云,这个没什么可说,但是!containsBeanDefinition(beanName)就 比较重要,他是在检查如果当加载的XML配置文件中不包含beanName所对应的配置,就只能到parentBeanFactory 去尝试加载,然后再去递归调用getBean方法。

6、转换成RootBeanDefinition

  将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition。
因为从XML配置文件中读取到的Bean信息是存储在GenericBeanDefinition中的,所有的Bean后续处理都是针对于RootBeanDefinition,所以这里需要进行转换,同时,如果父类bean不为空的话,则会一并合并父类的属性。

7、寻找依赖

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

8、针对不同的scope进行bean的创建

  在Spring中存在着不同的scope,默认的scope是single,但是还有些其他的如prototype、request之类的,在这里,Spring会根据不同的scope配置进行初始化策略。

8.1获取单例bean

  经过在前面的分析,我们已经知道Spring获取一个单例bean会先从缓存中获取,但是若缓存中不存在,那么就要从头开始加载了,而Spring使用getSingleton的重载方法实现了bean的加载过程。

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		//同步全局变量
		synchronized (this.singletonObjects) {
			//首先检查对应的bean是否已经加载过,因为singleton模式其实就是复用以创建的bean
			Object singletonObject = this.singletonObjects.get(beanName);
			//如果为空才进行singleton的bean的初始化
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					//初始化bean
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					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) {
					//加入缓存
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

以上代码中实际上是创建获取bean前后做的一些准备及处理操作,而正真获取单例bean其实是在用回调方法中实现的,其实现逻辑在ObjectFactory类的singletonFactory中实现的。我们先来看看上面代码大致做了哪些内容:

1)检查缓存是否已经加载过
2)若没有加载,则记录beanName的正在加载状态
3)加载单例前记录bean正在加载的状态
  这一步是在beforeSingletonCreation方法中实现的,跟踪进去,貌似方法中什么也没做,实际上不是的,之所以这样想,实际上你可能忽略了this.singletonsCurrentlyInCreation.add(beanName)这句代码,是的,正是这句话,将当前bean正在加载的状态记录到了singletonsCurrentlyInCreation中。

protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && >!this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}

4)通过调用参数传入的ObjectFactory的个体Object方法实例化bean
4)通过调用参数传入的ObjectFactory的个体Object方法实例化bean
5)加载单例后的处理方法
  同步骤3一样,当bean加载结束后也要记录bean加载完成的状态,实际上就是从缓存中将正在加载bean的状态移除掉,即 if 条件中this.singletonsCurrentlyInCreation.remove(beanName)所做的事。

protected void afterSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName)  && >!this.singletonsCurrentlyInCreation.remove(beanName)) {
					throw new IllegalStateException("Singleton '" + beanName + "' isn't >currently in creation");
		}
	}

6)将结果记录至缓存并珊瑚加载bean过程中所记录的各种辅助状态

protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.put(beanName, singletonObject);
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}

7)返回处理结果

以上就是加载bean的整体逻辑,但是我们还没有开始对bean加载功能开始探索,我们下面开始看看回调中的创建bean是怎么回事!先回顾一下之前的定义,也就是ObjectFactory中的createBean方法,这里才是核心。

sharedInstance = getSingleton(beanName, () -> {
			try {
				//创建bean
				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.2、准备创建bean

跟踪了这么多Spring的代码,我们发现一个规律,在函数中真正干货的方法其实都是以do开头的,在这里似乎也不例外,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;

		//锁定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 {
			// 给BeanPostProcessors一个机会来返回代理来替代真正的实例
			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 {
			// 我们要关注的方法 创建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)对override属性进行标记及验证
3)应用初始化的前后处理器,解析指定bean是否存在初始化前的短路操作
4)创建bean

我们不指望能在一个方法中完成所有复杂逻辑,上面代码中我们重点关注第4步doCreateBean方法中bean的创建,其他步骤大家有兴趣可以看下代码了解。

8.3、创建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使用对应的策略创建新的实例,如:工厂方法,构造函数自动注入,简单初始化
			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;
			}
		}

		// 是否需要提早曝光条件:单例 & 允许循环依赖 & 当前bean正在创建中
		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初始化完成前将创建实例的ObjectFactory加入工厂
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		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) {
				//如果exposedObject 在初始化方法中没有被改变,也就是没有被增强
				if (exposedObject == bean) {
					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一定是创建的
					// actualDependentBeans不为空则表示当前bean创建后其依赖的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 " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

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

		return exposedObject;
	}

之所以说它是一段复杂的代码,是因为这一部分最为关键,还是老规矩,看看整个函数的概要思路,整个过程大概可以分为八步:

1)如果是单例,则首先要清除缓存(remove)
2)实例化bean,将BeanDefinition转换为BeanWrapper
3)MergedBeanDefinitionPostProcessors的应用(抱歉,这一步我还没搞懂,留个标记,日后回来看看)
4)依赖处理
   在Spring中会有循环依赖的情况,例如,A中有B的属性,而B中又含有A属性时,就会构成一个循环依赖。Spring在处理循环依赖的时候,是通过中间缓存来解决的,并且Spring只解决单例中的循环依赖
5)属性填充,将所有的属性填充到bean中实例中
6)循环依赖检查
  上面提到,Spring中只解决单列中的循环依赖,而对于prototype的bean,Spring没有解决,能做的就是抛出异常。
7)注册DisposableBean
  如果配置了destory-methd,这里需要注册以便于在销毁bean的时候调用
8)完成创建并返回

这里 由于 加载实例化bean过于复杂,也比较重要,为了突出重点,我就单独在另外一篇博文中做详细介绍:Spring源码阅读▶㈡bean的实例化,这里不再赘述。

9、类型转换

  当走到这里返回bean基本已经结束了,通常对该方法的调用参数requiredType是为空的,但是也有可能存在这样的情况。返回的bean是String,但是requiredType是Integer类型,那么这时候类型转换就起作用了,他的功能是将返回的bean转换为requiredType所对应的类型。

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

代码就是这些,有点复杂,还是要多看~
————————————————————————————————
(完)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值