Java教程

Spring源码 - 容器刷新

本文主要是介绍Spring源码 - 容器刷新,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

# Spring源码 - 容器刷新

Spring版本:5.3.13-release


# 1、IOC(Inversion Of Control)思想–控制反转

1、控制反转:

  • 将对象创建与对象之间的调用过程,全权交给Spring进行管理。

2、使用IOC的目的:

  • 解耦

3、IOC是一种思想,DI就是对IOC的一种实现方式:

  • DI(Dependency Injection)依赖注入:容器能知道哪个组件(类)运行的时候,需要另外一个类(组件);容器通过反射的形式,将容器中准备好的的Bean实例对象注入(利用反射给属性赋值)到实例中去。

只要是容器管理的组件,都能使用容器提供的强大功能。


# 2、Spring中的IOC接口

1、IOC思想是基于IOC容器完成,IOC容器底层就是对象工厂

2、Spring提供IOC容器实现的两种方式:

  • BeanFactory接口:IOC容器最基本的实现方式,是Spring内部使用的接口,供Spring内部使用。在加载配置文件的时候,不会去立即创建配置文件中配置的对象,而是在获取的或使用对象的时候创建对象。
  • ApplicationContext接口:BeanFactory的子接口,提供了比BeanFactory更强大的功能。加载配置文件的时候就创建配置文件中声明的对象。在实际开发中,开发人员一般都是实现ApplicationContextAware接口,通过ApplicationContext去获取容器中的Bean

# 3、容器刷新AbstractApplicationContext#refresh()

Spring的容器刷新尤为重要,容器刷新的源码为AbstractApplicationContext#refresh()

AbstractApplicationContext#refresh()源码:

@Override
	public void refresh() throws BeansException, IllegalStateException {
         // 进入同步代码块, 保证线程安全
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// Prepare this context for refreshing.
			// 准备刷新上下文环境。作用就是初始化一些状态和属性, 后后续的工作做准备
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			// 创建容器对象 : DefaultListableBeanFactory
			// 加载 xml 配置文件或者配置类的属性到当前 beanFactory 中。最重要的就是 BeanDefinition
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			// beanFactory的准备工作。对各种属性进行填充
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				// 子类覆盖方法做额外处理, 此处我们自己一般不做任何扩展工作。默认没有实现。但是可以查看 web 中的代码, 是有具体实现的。
				// 这个方法是模板方法设计模式的体验, 默认无任何实现, 预留给子类扩展使用
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");

				// Invoke factory processors registered as beans in the context.
				// 调用各种 beanFactory 处理器
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				// 注册 Bean 处理器。这里只是单纯的注册功能, 真正调用的是 getBean 方法
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// Initialize message source for this context.
				// 为上下文初始化 message 源, 即不同语言的消息体, 做国际化处理。
				initMessageSource();

				// Initialize event multicaster for this context.
				// 初始化事件监听多路广播器
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				// 预留给子类, 用于初始化其他的 Bean
				onRefresh();

				// Check for listener beans and register them.
				// 在所有注册的 Bean 中查找 listener beans 并注册到消息消息广播中
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				// 初始化剩下的单实例 Bean(非惰性)
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				// 完成容器刷新。通知生命周期处理器 lifecycle processor 刷新过程。同时发出 ContextRefreshEvent 告知别人容器已完成刷新。
				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.
				// 防止 已经创建的 Bean 占用资源, 在异常处理中, 销毁在异常之前创建的单例 Bean
				destroyBeans();

				// Reset 'active' flag.
				// 重置容器 active 标志为 false 状态
				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();
				contextRefresh.end();
			}
		}
	}

refresh()中一共12个方法:

  • prepareRefresh(): 准备刷新上下文环境。作用就是初始化一些状态和属性, 后后续的工作做准备。
  • obtainFreshBeanFactory():字面意思是获取新鲜的BeanFactory,这里获取到的BeanFactoryDefaultListableBeanFactory。获取到BeanFactory之后ApplicationContext就具备了BeanFactory的各项功能,可以对Bean进行各种基础操作。
  • prepareBeanFactory()BeanFactory的准备工作。对各种属性进行填充。
  • postProcessBeanFactory():对获取的BeanFactory做后置增强处理,默认没有实现,子类覆盖方法做额外处理。但是在WEB中这里是有具体实现的。模板方法设计模式。
  • invokeBeanFactoryPostProcessors():调用各种BeanFactory增强处理器BeanFactoryPostProcessor及其子接口BeanDefinitionRegistryPostProcessor。注意,这里调用的各种BeanFactory的增强处理器是在Bean实例化之前。
  • registerBeanPostProcessors():注册BeanPostProcessor处理器。这里只是单纯的注册功能, 真正调用的是 getBean()方法。
  • initMessageSource():为上下文初始化Message源, 即不同语言的消息体做国际化处理。
  • initApplicationEventMulticaster():初始化事件监听多路广播器。
  • onRefresh():预留给子类, 用于初始化其他的 Bean。
  • registerListeners():在所有注册的Bean中查找listener beans并注册到消息消息广播中。
  • finishBeanFactoryInitialization():初始化剩下的单实例Bean(非惰性)。
  • finishRefresh():完成容器刷新。通知生命周期处理器lifecycle processor刷新过程。同时发出 ContextRefreshEvent告知别人容器已完成刷新。

由于这里总共有12个方法,源码篇幅较多,所以分为12篇分析每个方法的源码。

GitHub源码地址:https://github.com/kapbc/kapcb-spring-source/tree/master/Spring-Framework-v5.3.13

备注:此文为笔者学习Spring源码的笔记,鉴于本人技术有限,文中难免出现一些错误,感谢大家批评指正。

这篇关于Spring源码 - 容器刷新的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!