springIOC源码深度解析

之前没有意识到阅读优秀框架源码的重要性,直到我阅读完mybatis、spring IOC、AOP, springMVC的源码,从中学了很多底层的知识,好比java的反射内省,jdk动态代理,cglib动态代理,体会到源码中使用了各类设计模式,使得框架具备很是强大的扩展性,那个时候我才发现框架也是很美的。废话很少说,下面开始咱们的SpringIOC源码之旅。java

本文采用的源码版本是5.2.x。为了咱们更好地理解springIOC,咱们使用的是xml的方式,实际开发中大部分都是是用注解的方式,经验告诉我,从理解源码的角度上来说,xml配置是最好不过了。node

阅读源码的建议:去spring官网下载最新的源码,对照着看,否则根本看不下去,以前我就吃过亏,自觉得看书就能把源码弄明白,当时真是太天真了,看了几页就放弃了,由于根本就看不懂。spring

本文假定读者已经有spring相关的使用基础,好比如何创建工程,引入spring相关的依赖,并会使用单元测试。bootstrap

引言

阅读源码最大的难点就是入口难找,经验告诉咱们,咱们平时使用到的源码方式就是阅读的入口,这和咱们平时开发都是息息相关的。设计模式

建一个maven工程,添加相关依赖,使用单元测试来测试获取bean的流程。缓存

下面咱们来看看咱们平时都是怎么使用的springIOC:bash

下面是咱们平时获取一个bean的原始方式:session

public class TestSpring {
    @Test
    public void testSpring() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");
        Student student = (Student) ctx.getBean("student");
        System.out.println(student);
    }
}
复制代码

在resource文件夹下新建一个application.xml文件,一般叫 application.xml 或 application-xxx.xml 就能够了,并配置以下:mybatis

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    <bean id="student" class="com.sjc.spring.po.Student">
        <!-- String类型 -->
        <property name="name" value="jiangcong"></property>
        <!-- Integer类型 -->
        <property name="age" value="18"></property>
        <!-- 引用类型 -->
        <property name="course" ref="course"></property>
    </bean>

    <!-- 该类有一个初始化方法 -->
    <bean id="course" class="com.sjc.spring.po.Course"
          init-method="init">
        <!-- String类型 -->
        <property name="name" value="spring"></property>
    </bean>
</beans>

复制代码

Student类app

public class Student {

	private String name;
	private Integer age;

	private Course course;
  //... 省略getter/setter方法
}
复制代码

Course类

public class Course {

	private String name;
	//... 省略getter/setter方法
}
复制代码

例子很简单,可是也够引出本文的主题了,探索spring容器如何加装配置文件,以及如何为咱们实例化bean,使得咱们经过getBean("student")就能够获取到一个Student类的实例,从而理解spring中核心的IOC、DI。

开始阅读源码以前,先介绍一下Spring重要的接口,这里不要求你们掌握,只是到时候进入源码阅读部分时候,脑子里有个印象,再来查找这部分的知识就行了。

Spring重要接口介绍

BeanFactory继承体系

BeanFactory继承体系类型图

看到这些错综复杂的类关系图,咱们不由感慨,spring的庞大。那么spring为啥要定义这么多接口呢?由于每一个接口都有它使用的场合,各个接口之间具备必定的职责,可是又互不干扰,这就是设计模式中的接口隔离原则。你就想一下,若是把这些功能全都在一两个接口实现,那且不是乱成一团糟。

下面介绍主要类的主要功能:

BeanFactory:

接口主要定义了IOC容器的基本行为,好比根据各类条件获取Bean。这里使用了工厂模式。

ListableBeanFactory:

从名字能够看出来,这个接口的特色就是能够生产实例列表,好比根据类型获取Bean实例获取的是列表Bean实例

HierarchicalBeanFactory:

主要是实现了Bean工厂的分层。

AutowireCapableBeanFactory:

自动装配的Bean工厂

这个工厂接口继承自BeanFacotory,它扩展了自动装配的功能,根据类定义BeanDefinition装配 Bean、执行前、后处理器等。

ConfigurableBeanFactory

复杂的配置Bean工厂

ConfigurableListableBeanFactory

这个类很是之庞大,这个工厂接口总共有83个接口,包含了BeanFactory体系目前的全部方法。

BeanDefinitionRegistry

用来操做定义在工厂内部的BeanDefinition对象。好比注册BeanDefinition获取BeanDefinition

BeanDefinition继承体系

ApplicationContext继承体系

源码解析篇

建立IOC容器

介绍完了主要的接口,咱们进入源码分析

分析入口是: AbstractApplication#refresh()

整个容器初始化流程大致能够分为12步,想对哪一步骤感兴趣的读者能够自行决定将其做为分支入口了解其原理。这里我分析第2步和第11步,也就是IOC最关键的流程:建立BeanFactory的流程和Bean初始化的流程。为了省略篇幅,省略掉了相关干扰项,好比try/catch块。

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			// 1: 刷新预处理
			// 设置Spring容器的启动时间,撤销关闭状态,开启活跃状态。
			// 初始化属性源信息(Property)
			// 验证环境信息里一些必须存在的属性
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			// 2:
			// a) 建立IOC容器(DefaultListableBeanFactory)
			// b) 加载解析XML文件(最终存储到Document对象中)
			// c) 读取Document对象,并完成BeanDefinition的加载和注册工做
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			// 3: 对IOC容器作一些预处理(设置一些公共属性)
			prepareBeanFactory(beanFactory);

				// 4:
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// 5:调用BeanFactoryPostProcessor后置处理器对BeanDefinition处理
				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				// 6: 注册BeanPostProcessor后置处理器
				registerBeanPostProcessors(beanFactory);

				// 7: 初始化一些消息源(好比处理国际化的i18n等消息资源)
				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				// 8: 初始化应用事件广播器
				initApplicationEventMulticaster();

				// 9:初始化一些特殊的bean
				// Initialize other special beans in specific context subclasses.
				onRefresh();
				// 10:注册一些监听器
				// Check for listener beans and register them.
				registerListeners();
				// 11:实例化剩余的单例bean(非懒加载方式)
				// 注意事项: Bean的IOC、ID和AOP都是发生在此步骤
				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);
				// 12: 完成刷新时,须要发布对应的事件
				// Last step: publish corresponding event.
				finishRefresh();
		}
		//...省略try/catch代码块
		
复制代码

咱们跟进第2步obtainFreshBeanFactory(),这里主要完成XML文件的解析(最终存储到Document对象中),读取Document对象,并完成BeanDefinition的加载和注册工做,返回一个Bean工厂DefaultListableBeanFactory,读者的能够对照着上面的UML类关系图,找到DefaultListableBeanFactory的位置,体会一下这个类的做用。

咱们接着进入到AbstractRefreshableApplicationContext#refreshBeanFactory

这里就会建立一个比较重要的容器IOC容器工厂,DefaultListableBeanFactory,咱们配置文件的信息就以BeanDefinition对象形式存放在这里,咱们关注loadBeanDefinitions(beanFactory);这行代码,这里就是加载咱们的配置文件封装到BeanDefinition并存到DefaultListableBeanFactory的逻辑实现,这里只是定义了一个钩子方法,实现主要由子类去实现,有点像设计模式中的抽象模板方法。

protected final void refreshBeanFactory() throws BeansException {
		// 若是以前有IOC容器,则销毁
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
    // 建立IOC容器,也就是DefaultListableBeanFactory
    DefaultListableBeanFactory beanFactory = createBeanFactory();
    beanFactory.setSerializationId(getId());
    // 设置工厂的属性:是否容许BeanDefinition覆盖和是否容许循环依赖
    customizeBeanFactory(beanFactory);
    // 调用BeanDefinition的方法,在当前类中定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器。
    loadBeanDefinitions(beanFactory); // 钩子方法
    synchronized (this.beanFactoryMonitor) {
    this.beanFactory = beanFactory;
    }
    //...省略try/catch代码块
	}
复制代码

这里咱们主要关心xml配置文件对应的实现类,也有注解的形式,感兴趣的读者能够将此做为分支进行深刻研究。

咱们进到 AbstractXmlApplicationContext#loadBeanDefinitions

这里咱们看到了接口隔离设计原则和单一职责原则,初步体会到了定义这么多的接口的好处。咱们先来看BeanFactory的继承体系中, DefaultListableBeanFactory是实现了BeanDefinitionRegistry接口,拥有了注册BeanDefinition的能力,但这里传给XmlBeanDefinitionReader这个BeanDefinition阅读器的只是将BeanDefinitionRegistry这个拥有注册BeanDefinition功能接口传入(咱们看XmlBeanDefinitionReader构造函数就知道,public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) ),其余的能力还在DefaultListableBeanFactory中,这实际上是保护了DefaultListableBeanFactory,体现了接口隔离的效果。

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		// 建立一个BeanDefinition阅读器,经过阅读XML文件,真正完成BeanDefinition的加载和注册
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's // resource loading environment. beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // Allow a subclass to provide custom initialization of the reader, // then proceed with actually loading the bean definitions. initBeanDefinitionReader(beanDefinitionReader); // 委托给BeanDefinitions阅读器去加载BeanDefinition loadBeanDefinitions(beanDefinitionReader); } 复制代码

咱们接着进入到loadBeanDefinitions方法中,

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		// 获取资源的定位
		// 这里getConfigResources是一个空实现,真正实现是调用子类的获取资源定位的方法
		// 好比:ClassPathXmlApplicationContext中进行了实现
		// 		而FileSystemXmlApplicationContext没有使用该方法
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			// XML Bean读取器调用其父类AbstractBeanDefinitionReader读取定位的资源
			reader.loadBeanDefinitions(configResources);
		}
		// 若是子类中获取的资源定位为空,则获取FileSystemXmlApplicationContext构造方法中setConfigLocations方法设置的资源
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			// XML Bean读取器调用其父类AbstractBeanDefinitionReader读取定位的资源
			reader.loadBeanDefinitions(configLocations);
		}
	}
复制代码

这里咱们主要看

reader.loadBeanDefinitions(configLocations),并进入到

public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
		// 获取在IOC容器初始化过程当中设置的资源加载器
		ResourceLoader resourceLoader = getResourceLoader();
		if (resourceLoader == null) {
			throw new BeanDefinitionStoreException(
					"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
		}

		if (resourceLoader instanceof ResourcePatternResolver) {
			// Resource pattern matching available.
				Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
				// 委派调用其子类XmlBeanDefinitionReader的方法,实现加载功能
				int count = loadBeanDefinitions(resources);
				if (actualResources != null) {
					Collections.addAll(actualResources, resources);
				}
				if (logger.isTraceEnabled()) {
					logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
				}
				return count;
			}
			// ...省略try/catch代码块
}
复制代码

咱们进入到其子类XmlBeanDefinitionReader#loadBeanDefinitions

这里会获取XML文件的InputStream流,并封装到InputSource中,咱们主要看doLoadBeanDefinitions这个具体的解析过程。

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		 //...省略若干代码
			// 将资源文件转为InputStream的IO流
			InputStream inputStream = encodedResource.getResource().getInputStream();
				// 从InputStream中获得XML的解析流
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				// 具体的解析过程
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			//...省略try/catch代码块
			
	}
复制代码

咱们来到XmlBeanDefinitionReader#doLoadBeanDefinitions:

这里主要是将XML封装成Document对象,而后对Document对象的解析操做,完成BeanDefinition的加载和注册工做。通过千辛万苦,咱们终于来到这一步,不容易啊!

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

			// 经过DOM4加载解析XML文件,最终造成Document对象
			Document doc = doLoadDocument(inputSource, resource);
			// 经过对Document对象的解析操做,完成BeanDefinition的加载和注册工做
			int count = registerBeanDefinitions(doc, resource);
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + count + " bean definitions from " + resource);
			}
			return count;
			// .../省略try/catch代码块

复制代码

咱们来看看BeanDefinition是如何注册的

进入到XmlBeanDefinitionReader#registerBeanDefinitions

这里 很好地利用了面向对象中单一职责原则,将逻辑处理委托给单一的类进行处理,好比: BeanDefinitionDocumentReader

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		// 使用DefaultBeanDefinitionDocumentReader实例化BeanDefinitionDocumentReader
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		// 记录统计前BeanDefinition的加载个数
		int countBefore = getRegistry().getBeanDefinitionCount();
		// 加载及注册bean
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		// 记录本次加载的BeanDefinition个数
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}
复制代码

咱们进入到BeanDefinitionDocumentReader#registerBeanDefinitions

并进入到其默认实现类DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions

protected void doRegisterBeanDefinitions(Element root) {
		// 这里使用了委托模式,将具体的BeanDefinition解析工做交给了BeanDefinitionParserDelegate去完成
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);

		//...省略掉了默认命名空间的代码
		// 在解析Bean定义以前,进行自定义的解析,加强解析过程的可扩展性
		preProcessXml(root); // 钩子方法
		// 委托给BeanDefinitionParserDelegate,从Document的根元素开始进行BeanDefinition的解析
		parseBeanDefinitions(root, this.delegate);
		// 在解析Bean定义以后,进行自定义的解析,增长解析过程的可扩展性
		postProcessXml(root); // 钩子方法

		this.delegate = parent;
	}
复制代码

这里咱们主要关心parseBeanDefinitions

进入到DefaultBeanDefinitionDocumentReader#parseBeanDefinitions

这里就比较重要了,遍历解析Document对象的全部子节点,这里咱们只关心parseDefaultElement,也就是 bean标签、import标签、alias标签,则使用默认解析规则

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		// 加载的Document对象是否使用了Spring默认的XML命名空间(beans命名空间)
		if (delegate.isDefaultNamespace(root)) {
			// 获取Document对象根元素的全部子节点(bean标签、import标签、alias标签和其余自定义标签context、aop等)
			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;
					// bean标签、import标签、alias标签,则使用默认解析规则
					if (delegate.isDefaultNamespace(ele)) {
						parseDefaultElement(ele, delegate);
					}
					else { //像context标签、aop标签、tx标签,则使用用户自定义的解析规则解析元素节点
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}
复制代码

咱们进入到DefaultBeanDefinitionDocumentReader#parseDefaultElement

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		// 解析<import>标签
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		// 解析<alias>标签
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		// 解析bean标签
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			// 递归调用
			doRegisterBeanDefinitions(ele);
		}
	}
复制代码

这里咱们主要看标签的解析,其余的读者感兴趣的话能够本身去看。

咱们进入到DefaultBeanDefinitionDocumentReader#processBeanDefinition

BeanDefinitionParserDelegate#parseBeanDefinitionElement会解析BeanDefinition,并封装到BeanDefinitionHolder,

BeanDefinitionReaderUtils#registerBeanDefinition会最终将BeanDefinition注册到BeanDefinitionRegistry(DefaultListableBeanFactory)中,并存入到map中:private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

感兴趣的读者能够继续跟踪,这里咱们终于解析完了BeanDefinition。完成了AbstractApplicationContext#refresh() 的第2步:XML文件的解析和BeanDefinition的加载和注册工做

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		// 解析<bean>标签,获取BeanDefinition
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// 注册最终的BeanDefinition到BeanDefinitionRegistry(DefaultListableBeanFactory)
				// Register the final decorated instance.
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}
复制代码

实例化Bean

咱们来看看AbstractApplicationContext#refresh()的第11步,这步很重要、很重要、很重要。。。

这里完成了单例Bean的实例化,Bean的IOC、ID和AOP都是发生在这步

AbstractApplicationContext#finishBeanFactoryInitialization

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
//... 省略掉了若干代码
// Instantiate all remaining (non-lazy-init) singletons.
		// 实例化单例bean
		beanFactory.preInstantiateSingletons();
}
复制代码

咱们进入到DefaultListableBeanFactory#preInstantiateSingletons

这里先了解一下,BeanFactory和FactoryBean的区别,

  • BeanFactory是spring顶级接口,是spring基础容器,它负责管理bean实例。

  • FactoryBean只是spring容器中被管理的一个bean对象,只是说这个bean它的能力就是产生另外的对象。

  • BeanFactory是一个包容万物的大工厂

  • FactoryBean是一个只能生产指定对象的小工厂,并且这个小工厂还被大工厂给管理。

  • FactoryBean和普通的Bean实例,被Spring管理时,也是区别对待的。经过&前缀来区分FactoryBean和普通的Bean实例

public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		// 触发全部非懒加载方式的单例bean的建立
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				// 若是bean是一个FactoryBean,则走下面的方法
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else { // 普通bean走下面的方法
					getBean(beanName);
				}
			}
		}
		//...省略掉若干代码
}
复制代码

这里咱们走的是普通的Bean

进入AbstractBeanFactory#getBean,

并进入到AbstractBeanFactory#doGetBean

这个方法,主要分为两个步骤:

  1. 从缓存中获取单例Bean,若是获取到了就检测,若是获取出来的Bean是FactoryBean,则须要从FactoryBean实例中产生一个对象
  2. 若是没有获取到Bean,则须要经过BeanDefinition来实例化一个Bean返回
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

		// 获取bean的名称
		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		// 从缓存中获取单例bean
		Object sharedInstance = getSingleton(beanName);
		// 若是获取到单例bean,则走下面代码
		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 + "'");
				}
			}
			// 若是取出来的Bean实例是FactoryBean的Bean实例,则须要从FactoryBean实例中产生一个对象实例
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else { // 若是没有获取到单例bean,则走下面代码
			// Fail if we're already creating this bean instance: // We're assumably within a circular reference.
			// 若是原型模式的Bean发生循环引用,则直接不处理,直接抛异常
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			//...省略了检测BeanDefinition是否在Factory中的代码

			try {
				// 获取实例化的bean的BeanDefinition对象
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				// 检查该BeanDefinition对象对应的Bean是不是抽象的
				checkMergedBeanDefinition(mbd, beanName, args);
				//...省略检测代码

				// Create bean instance.
				// 若是是单例的Bean,看下面代码
				if (mbd.isSingleton()) {
					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;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				else if (mbd.isPrototype()) { // 原型
					//...省略了处理原型模式Bean的分支
				}

				else { 
					//...省略了好比处理request、session级别的bean的分支
		    }

		return (T) bean;
	}
复制代码

咱们主要来看这段代码(重要):

这里用到了Java8的lambda表达式

// Create bean instance.
				// 若是是单例的Bean,看下面代码
				if (mbd.isSingleton()) {
					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;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
复制代码

进入到DefaultSingletonBeanRegistry#getSingleton

这里处理了循环依赖的问题,什么是循环依赖,以及spring如何解决循环依赖,期待我下一篇文章。

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				//...省略检测代码
				// 建立以前,设置一个建立中的标识
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					// 调用匿名内部类获取单例对象
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
	       //...省略catch代码块
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					// 消除对象建立中的标识
					afterSingletonCreation(beanName);
				}
				// 将产生的单例Bean放入缓存中(总共三级缓存)
				if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}
复制代码

上面 singletonObject = singletonFactory.getObject();调用的是lambda表达式中的createBean(beanName, mbd, args)方法。

咱们进入到其实现类

AbstractAutowireCapableBeanFactory#createBean

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {
      
     //...省略若干代码块
     // 完成Bean实例的建立(实例化、填充属性、初始化)
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
}
复制代码

进入到咱们关心的

AbstractAutowireCapableBeanFactory#doCreateBean

这里完成完成Bean实例的建立,包括三个步骤:

  1. 实例化

    默认调用无参构造实例化Bean,构造参数依赖注入就是发生在这个步骤

  2. 属性填充(DI依赖注入发生在此步骤)

    利用反射和内省技术进行属性设置

  3. 初始化(AOP发生在此步骤)

    也是利用反射调用初始化方法好比

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);
		}
		// bean初始化第一步:默认调用无参构造实例化Bean
		// 构造参数依赖注入,就是发生在这一步
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		// 实例化后的Bean对象
		final Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		//...省略若干代码

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		// 解决循环依赖的关键步骤
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		// 若是须要提早暴露单例Bean,则将该Bean放入三级缓存中
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			// 将刚建立的bean放入三级缓存中singleFactories(key是beanName,value是FactoryBean)
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			// bean初始化第二步: 填充属性(DI依赖注入发生在此步骤)
			// 这里主要分为两种状况:
			// 1.对于非集合类型的属性,直接使用反射和内省机制去进行属性设置
			// 2。对于集合类型的属性,将其属性值解析为目标类型的集合后直接赋值给属性
			populateBean(beanName, mbd, instanceWrapper);
			// bean初始化第三步:调用初始化方法,完成bean的初始化操做(AOP发生在此步骤)
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		//... 省略catch块代码

		//...省略若干代码
		return exposedObject;
	}
复制代码

到这里,SpringIOC容器对Bean定义的资源文件的加载、解析和依赖注入已经解析完毕,如今SpringIOC容器中管理了一系列靠依赖关系联系起来的Bean,程序不须要应用本身手动建立所需对象,SpringIOC容器会在咱们使用的时候自动为咱们建立,而且为咱们注入好相关的依赖,这就是Spring核心功能的控制反转和依赖注入的相关功能,所谓的反转,也就是将建立Bean的权利交给spring进行管理。

相关文章
相关标签/搜索