ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Spring源码 - 容器刷新

2022-01-08 23:06:13  阅读:161  来源: 互联网

标签:容器 BeanFactory Spring Bean 源码 context IOC


# 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源码的笔记,鉴于本人技术有限,文中难免出现一些错误,感谢大家批评指正。

标签:容器,BeanFactory,Spring,Bean,源码,context,IOC
来源: https://blog.csdn.net/qq_43911324/article/details/122344500

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有