Spring IOC源码深度剖析

  • Post author:
  • Post category:其他


看源码


  • 好处:提高培养代码架构思维、深入理解框架

  • 原则

  1. 定焦原则:抓主线,比如BeanFactory的创建流程、Bean对象创建流程、lazy-int延迟加载流程、SpringIoc循环依赖原理,其他的不关心

  2. 宏观原则:站在上帝视角,关注源码结构和业务流程(淡化具体某行代码的编写细节),不需要扣太细,不然读不下去

  • 读源码的方法和技巧

  1. 断点(观察调用栈)

  2. 反调(Find Usages


    ),不知道改方法在哪个地方被调用了,右键find Usages

  3. 经验(


    spring


    框架中


    doXXX


    ,做具体处理的地方)

  • Spring


    源码构建

  1. 下载源码(


    github




  2. 安装


    gradle 5.6.3


    (类似于


    maven





    Idea 2019.1 Jdk 11.0.5

  3. 导入(耗费一定时间)

  4. 编译工程(顺序:


    core-oxm-context-beans-aspects-aop





    工程


    —>tasks—>compileTestJava


一、Spring IoC


容器初始化主体流程


1.1、Spring IoC


的容器体系


IoC


容器是


Spring


的核心模块,是抽象了对象管理、依赖关系管理的框架解决方案。


Spring


提供了很多的容器,其中 BeanFactory


是顶层容器(根容器),不能被实例化,它定义了所有


IoC


容器必须遵从的一套原则,具体的容器实现可以增加额外的功能,比如我们常用到的ApplicationContext


,其下更具体的实现如 ClassPathXmlApplicationContext


包含了解析


xml


等一系列的内容,AnnotationConfigApplicationContext


则是包含了注解解析等一系列的内容。


Spring IoC


容器继承体系非常聪明,需要使用哪个层次用哪个层次即可,不必使用功能大而全的。

 ApplicationContext是容器的高级接口,BeanFacotry(顶级容器/根容器,规范了/定义了容器的基础行为)
 Spring应用上下文,官方称之为 IoC容器(错误的认识:容器就是map而已;准确来说,map是ioc容器的一个成员, 叫做单例池,singletonObjects。容器是一组组件和过程的集合,包括BeanFactory、单例池、BeanPostProcessor等以及之间的协作流程)

BeanFactory


顶级接口方法栈如下:



BeanFactory


容器继承体系:


通过其接口设计,我们可以看到我们一贯使用的


ApplicationContext


除了继承


BeanFactory


的子接口,还继承了ResourceLoader





MessageSource


等接口,因此其提供的功能也就更丰富了。下面我们以 ClasspathXmlApplicationContext


为例,深入源码说明


IoC


容器的初始化流程。


1.2、Bean生


命周期关键时机点



思路




创建一个类


LagouBean


,让其实现几个特殊的接口,并分别在接口实现的构造器、接口方法中断点,观察线程调用栈(调用了哪个类的哪个方法,分析出Bean


对象创建和管理关键点的触发时机。

LagouBean
package com.lagou.edu;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;


public class LagouBean implements InitializingBean, ApplicationContextAware {

	/*private ItBean itBean;

	public void setItBean(ItBean itBean) {
		this.itBean = itBean;
	}*/
	private int num;

	public void setNum(int num) {
		this.num = num;
	}

	/**
	 * 构造函数
	 */
	public LagouBean(){
		System.out.println("LagouBean 构造器...");
	}


	/**
	 * InitializingBean 接口实现
	 */
	public void afterPropertiesSet() throws Exception {
		System.out.println("LagouBean InitializingBean#afterPropertiesSet...");
	}

	public void print() {
		System.out.println("print方法业务逻辑执行");
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		System.out.println("setApplicationContext....");
	}

	/**
	 * BeanFactoryPostProcessor的实现类构造函数...
	 * BeanFactoryPostProcessor的实现方法调用中......
	 * BeanPostProcessor 实现类构造函数...
	 * LagouBean 构造器...
	 * setApplicationContext....
	 * BeanPostProcessor 实现类 postProcessBeforeInitialization 方法被调用中......
	 * LagouBean afterPropertiesSet...
	 * BeanPostProcessor 实现类 postProcessAfterInitialization 方法被调用中......
	 * com.lagou.edu.LagouBean@6ad3381f
	 */
}



BeanPostProcessor


接口实现类

package com.lagou.edu;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;


public class MyBeanPostProcessor implements BeanPostProcessor {

	public MyBeanPostProcessor() {
		System.out.println("BeanPostProcessor 实现类构造函数...");
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if("lagouBean".equals(beanName)) {
			System.out.println("BeanPostProcessor 实现类 postProcessBeforeInitialization 方法被调用中......");
		}
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if("lagouBean".equals(beanName)) {
			System.out.println("BeanPostProcessor 实现类 postProcessAfterInitialization 方法被调用中......");
		}
		return bean;
	}
}


BeanFactoryPostProcessor接口实现类

package com.lagou.edu;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;


public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

	public MyBeanFactoryPostProcessor() {
		System.out.println("BeanFactoryPostProcessor的实现类构造函数...");
	}

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("BeanFactoryPostProcessor的实现方法调用中......");
	}
}

测试:
import com.lagou.edu.LagouBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class IocTest {

	/**
	 *  Ioc 容器源码分析基础案例
	 */
	@Test
	public void testIoC() {
		// ApplicationContext是容器的高级接口,BeanFacotry(顶级容器/根容器,规范了/定义了容器的基础行为)
		// Spring应用上下文,官方称之为 IoC容器(错误的认识:容器就是map而已;准确来说,map是ioc容器的一个成员,
		// 叫做单例池, singletonObjects,容器是一组组件和过程的集合,包括BeanFactory、单例池、BeanPostProcessor等以及之间的协作流程)

		/**
		 * Ioc容器创建管理Bean对象的,Spring Bean是有生命周期的,在特殊方法打断点可知 
	
		 *  bean构造函数执行、初始化方法执行 、Bean后置处理器的before/after方法:AbstractApplicationContext#refresh()#finishBeanFactoryInitialization()
		 *
		 *  Bean工厂后置处理器构造函数执行、Bean工厂后置处理器方法执行:AbstractApplicationContext#refresh()#invokeBeanFactoryPostProcessors()
		 *
		 *  Bean后置处理器构造函数执行:AbstractApplicationContext#refresh()#registerBeanPostProcessors()
		 */


		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
		LagouBean lagouBean = applicationContext.getBean(LagouBean.class);
		System.out.println(lagouBean);
	}


}


1.3、Spring IoC


容器初始化主流程


由上分析可知,


Spring IoC


容器初始化的关键环节就在


AbstractApplicationContext#refresh() 方


法中,我们查看 refresh 方


法来俯瞰容器创建的主体流程,主体流程下的具体子流程我们后面再一一来讨论。
public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			/**
			 * 第⼀步:刷新前的预处理
			 * 表示在真正刷新之前需要准备做的事情:
			 * 设置sping容器的启动时间
			 * 开启活跃状态,撤销关闭状态
			 * 验证环境信息里一些必要的属性
			 */

			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			/**
			 * 第⼆步:获取BeanFactory,有了bean工厂才能创建bean,默认实现是DefaultListableBeanFactory
			 *    读取配置文件信息,将<bean></bean>中的信息封装成BeanDefition 并注册到 BeanDefitionRegistry(是一个map)
			 */
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			// 第三步:BeanFactory的预准备⼯作(BeanFactory进⾏⼀些设置,⽐如context的类加载器等
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				// 第四步:BeanFactory准备⼯作完成后进⾏的后置处理⼯作
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				// 第五步: 实例化并调用实现了BeanFactoryPostProcessor接口的Bean
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				// 第六步:注册BeanPostProcessors(Bean的后置处理器)
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				// 第七步:初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
				initMessageSource();

				// Initialize event multicaster for this context.
				// 第八步:初始化事件分发器
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				// 第九步:⼦类重写这个⽅法,在容器刷新的时候可以⾃定义逻辑
				onRefresh();

				// Check for listener beans and register them.
				// 第⼗步:注册应⽤的监听器。就是注册实现了ApplicationListener接⼝的监听器
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				/**
				 * 第十一步:
				 * 初始化所有剩下的非懒加载的单例bean
				 * 初始化创建非懒加载方式的单例bean实例(未设置属性)
				 *    填充属性
				 *    初始化方法调用,(比如调用afterPropertiesSet方法、init-method方法)
				 *    调用BeanPostProcessor(bean后置处理器)对实例bean进行后处置
				 */
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				// 第⼗⼆步:完成context的刷新。主要是调⽤LifecycleProcessor的onRefresh()⽅法,并且发布事 (ContextRefreshedEvent)
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

二、

BeanFactory


创建流程


2.1 获取beanFactory子流程

2.2、

BeanDefi


nition加载解析及注册子流程






1


)该子流程涉及到如下几个关键步骤



Resource


定位:



指对


BeanDefi


nition


的资源定位过程。通俗讲就是找到定义


Javabean


信息的


XML文件,并将其封装成Resource


对象。


BeanDefi


nition


载入






把用户定义好的


Javabean


表示为


IoC


容器内部的数据结构,这个容器内部的数据结构就是BeanDefi


nition





注册


BeanDefi


nition





IoC


容器






2


)过程分析

1 子流程入口在AbstractRefreshableApplicationContext#refreshBeanFactory方法中


2 、依次调用多个类的


loadBeanDefi


nitions 方





—> AbstractXmlApplicationContext —>AbstractBeanDefinitionReader —> XmlBeanDefi


nitionReader一


直执行到XmlBeanDefinitionReader





doLoadBeanDefi


nitions 方



从xml中加载到beanDefinition

3、我们重点观察


XmlBeanDefi


nitionReader


类的


registerBeanDefi


nitions 方




4、此处我们关注两个地方:一个


createRederContext方


法,一个是DefaultBeanDefinitionDocumentReader


类的


registerBeanDefi


nitions方


法,先进入createRederContext 方法看看


5、我们可以看到,此处


Spring 首


先完成了


NamespaceHandlerResolver


的初始化。

6、


我们再进入


registerBeanDefi


nitions 方


法中追踪,调用了


DefaultBeanDefi


nitionDocumentReader#registerBeanDefi


nitions 方




7、进入doRegisterBeanDefinitions方法
8、进入parseBeanDefinitions方法
9、进入parseDefaultElement方法
10、进入processBeanDefinition方法

11、我们 可以在看看是怎么注册的,进入registerBeanDefinition方法
12、进入registerBeanDefinition方法,最后将BeanDefinition存入map集合中

三、

Bean


创建流程


Bean ⽣命周期的整个执⾏过程描述:

1)根据配置情况调⽤ Bean 构造⽅法或⼯⼚⽅法实例化 Bean。

2)利⽤依赖注⼊完成 Bean 中所有属性值的配置注⼊。

3)如果 Bean 实现了 BeanNameAware 接⼝,则 Spring 调⽤ Bean 的 setBeanName() ⽅法传⼊当前 Bean 的 id 值。

4)如果 Bean 实现了 BeanFactoryAware 接⼝,则 Spring 调⽤ setBeanFactory() ⽅法传⼊当前⼯⼚实例的引⽤。

5)如果 Bean 实现了 ApplicationContextAware 接⼝,则 Spring 调⽤ setApplicationContext() ⽅法传⼊当前 ApplicationContext 实例的引⽤。

6)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调⽤该接⼝的预初始化⽅法postProcessBeforeInitialzation() 对 Bean 进⾏加⼯操作,此处⾮常重要,Spring 的 AOP 就是利⽤它实现的。

7)如果 Bean 实现了 InitializingBean 接⼝,则 Spring 将调⽤ afterPropertiesSet() ⽅法。

8)如果在配置⽂件中通过 init-method 属性指定了初始化⽅法,则调⽤该初始化⽅法。

9)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调⽤该接⼝的初始化⽅法 postProcessAfterInitialization()。

此时,Bean 已经可以被应⽤系统使⽤了。

10)如果在 <bean> 中指定了该 Bean 的作⽤范围为 scope=”singleton”,则将该 Bean 放⼊ Spring IoC 的缓存池中,

将触发 Spring 对该 Bean 的⽣命周期管理;如果在 <bean> 中指定了该 Bean 的作⽤范围为 scope=”prototype”,则将该 Bean 交给调⽤者


11)如果 Bean 实现了 DisposableBean 接⼝,则 Spring 会调⽤ destory() ⽅法将 Spring 中的 Bean 销毁;

如果在配置⽂件中通过 destory-method 属性指定了 Bean 的销毁⽅法,则 Spring 将调⽤该⽅法对 Bean 进⾏销毁。

注意:Spring 为 Bean 提供了细致全⾯的⽣命周期过程,通过实现特定的接⼝或 <bean> 的属性设置,都可以对 Bean 的⽣命周期过程产⽣影虽然可以随意配置 <bean> 的属性,但是建议不要过多地使⽤ Bean 实现接⼝,因为这样会导致代码和 Spring 的聚合过于紧密


1、通过最开始的关键时机点分析,我们知道


Bean


创建子流程入口在AbstractApplicationContext#refresh()方法的fi


nishBeanFactoryInitialization(beanFactory)



2、进入finishBeanFactoryInitialization
3、进入preInstantiateSingletons方

法,我们找到下面部分的


代码,看到工厂


Bean


或者普通


Bean


,最终都是通过


getBean


的方法获取实例
4、进入getBean()
5、进入doGetBean()方法,do开头的是真正干活的,

我们直接找到核心部分
6、进入createBean
7、doCreateBean



版权声明:本文为LWYYYYYY原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。