上一篇咱们通过一个例子介绍初始化容器上下文相关内容,并通过两个示例代码看到了Spring在设计阶段为我预留的扩展点,和我们应该如何利用这两个扩展点在Spring初始化容器上下文阶段为我们提供服务。这一篇咱们接着往下看。

老这样子下回到refresh方法上来:

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing. 1、初始化上下文信息,替换占位符、必要参数的校验
			prepareRefresh();
			// Tell the subclass to refresh the internal bean factory. 2、解析类Xml、初始化BeanFactory
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 这一步主要是对初级容器的基础设计
			// Prepare the bean factory for use in this context. 	3、准备BeanFactory内容:
			prepareBeanFactory(beanFactory); // 对beanFactory容器的功能的扩展:
			try {
				// Allows post-processing of the bean factory in context subclasses. 4、扩展点加一:空实现,主要用于处理特殊Bean的后置处理器
				postProcessBeanFactory(beanFactory);
				// Invoke factory processors registered as beans in the context. 	5、spring bean容器的后置处理器
				invokeBeanFactoryPostProcessors(beanFactory);
				// Register bean processors that intercept bean creation. 	6、注册bean的后置处理器
				registerBeanPostProcessors(beanFactory);
				// Initialize message source for this context.	7、初始化消息源
				initMessageSource();
				// Initialize event multicaster for this context.	8、初始化事件广播器
				initApplicationEventMulticaster();
				// Initialize other special beans in specific context subclasses. 9、扩展点加一:空实现;主要是在实例化之前做些bean初始化扩展
				onRefresh();
				// Check for listener beans and register them.	10、初始化监听器
				registerListeners();
				// Instantiate all remaining (non-lazy-init) singletons.	11、实例化:非兰加载Bean
				finishBeanFactoryInitialization(beanFactory);
				// Last step: publish corresponding event.	 12、发布相应的事件通知
				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();
			}
		}
	}

obtainFreshBeanFactory

让聚焦到obtainFreshBeanFactory方法,根据名称和注释简单猜测下这个方法是获取一个新的beanFactory容器。接下我们进入obtainFreshBeanFactory:

	/**
	 * Tell the subclass to refresh the internal bean factory.
	 * @return the fresh BeanFactory instance
	 * @see #refreshBeanFactory()
	 * @see #getBeanFactory()
	 */
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		// 1、 new 一个DefaultListableBeanFactory实例,创建Spring初级容器、
		// 2、设置容器是否允许循环依赖、覆盖;
		// 3、解析xml生成BeanDefinition对象放入beanDefinitionMap容器
		refreshBeanFactory();
		// 获取ConfigurableListableBeanFactory方法
		return getBeanFactory();
	}

obtainFreshBeanFactory只有两个方法且getBeanFactory方法只是将成员变量this.beanFactroy进行了返回,所以这方法的核心在refreshBeanFactory。


	@Override
	public final ConfigurableListableBeanFactory getBeanFactory() {
		synchronized (this.beanFactoryMonitor) {
			if (this.beanFactory == null) {
				throw new IllegalStateException("BeanFactory not initialized or already closed - " +
						"call 'refresh' before accessing beans via the ApplicationContext");
			}
			return this.beanFactory;
		}
	}

refreshBeanFactory

接下来我们进入refreshBeanFactory方法中看下具体逻辑:

/**
	 * This implementation performs an actual refresh of this context's underlying
	 * bean factory, shutting down the previous bean factory (if any) and
	 * initializing a fresh bean factory for the next phase of the context's lifecycle.
	 */
	@Override
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			// new 一个DefaultListableBeanFactory实例,创建Spring初级容器
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			// 定制容器参数:allowBeanDefinitionOverriding 是否允许被覆盖、allowCircularReferences 是否允许循环引用
			customizeBeanFactory(beanFactory);
			// 开始解析并加载xml文件中的bean,将解析后的BeanDefinition放入beanDefinitionMap容器中
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

可以看到我们上述的猜测正确的,Spring是在refreshBeanFacotry设置成员属性beanFactory,这个后面getBeanFacotry方法才可以通过成员属性获取到,再回到refreshBeanFacotry方法中。在我们进入方法的时候先是一个判断,因为第一次进去所以直接看try-catch代码块内容。

看下第一个行代码:

createBeanFactory返回一个DefaultListableBeanFactory实力对象,看到这个对象我们还是不得不提一下他的类图。

DefaultListableBeanFactory类图

在Spring中,BeanFactory是核心接口,负责实例化、配置和管理bean的生命周期。

类图结构分析

  1. BeanFactory

    • 所有Spring容器的根接口,定义了Spring容器的基本行为。
  2. ListableBeanFactory

    • 继承自BeanFactory,增加了列出所有bean定义的功能。
  3. ConfigurableBeanFactory

    • 提供了对BeanFactory的额外配置能力,如设置类加载器和属性编辑器。
  4. SingletonBeanRegistry

    • 接口,用于注册和管理单例bean。
  5. DefaultSingletonBeanRegistry

    • SingletonBeanRegistry接口的默认实现,负责注册和解析单例bean。
  6. HierarchicalBeanFactory

    • 允许BeanFactory形成层级结构,父工厂可以被子工厂继承。
  7. AbstractBeanFactory

    • 抽象类,提供了BeanFactory接口的默认实现。
  8. AbstractAutowireCapableBeanFactory

    • 抽象类,扩展了AbstractBeanFactory,增加了自动装配功能。
  9. ConfigurableListableBeanFactory

    • 继承自ConfigurableBeanFactory和ListableBeanFactory,提供了更多配置和bean列表功能。
  10. DefaultListableBeanFactory

    • 具体的BeanFactory实现,继承自AbstractAutowireCapableBeanFactory和ConfigurableListableBeanFactory,是Spring中最常用的bean工厂实现。

介绍完DefaultListableBeanFactory类图接着往下看。

定制容器参数:allowBeanDefinitionOverriding 是否允许被覆盖allowCircularReferences 是否允许循环引用,这两个参数后面我们会重点关注,在Bean实例化的时候,这这里咱们就留一个印象。接下来接着看

记载Xml中的BeanDefinition

今日小结

通过对 `refresh` 方法中第二个核心方法 `obtainBeanFactory` 的解读,我们了解到通过 `createBeanFactory` 创建了 Spring 的初级容器,并定义了容器的两个核心参数:是否允许循环引用和是否允许覆盖。

我们还介绍了初级容器 `DefaultListableBeanFactory` 的类图,对 Spring 初级容器的初始化和结构有了初步了解。下一篇文章中,我们将开始讨论容器第一个重要成员:BeanDefiniton。

源码整体进度

目前整体进度梳理如下:

Spring框架中容器初始化的核心步骤和概念的概述:

  1. 初始化时间与容器状态:这是容器启动和初始化过程中需要考虑的基础属性。

  2. 构造方法:容器的构造方法开始整个初始化过程。

  3. ClassPathXmlApplicationContext:这是一个用于从类路径下的XML配置文件中加载Spring应用上下文的特定实现。

  4. 初始化容器上下文环境:在容器启动时,需要设置和初始化容器的上下文环境。

  5. 属性值替换占位符:在配置文件中,可能包含一些占位符,需要在启动时被实际的属性值所替换。

  6. prepareRefresh方法:这个方法在刷新容器之前被调用,用于准备刷新操作,例如设置早期的事件多播器。

  7. PathMatchingResourcePatternResolver(this)实例:创建一个资源模式解析器实例,用于解析和匹配资源路径。

  8. 检测指定环境变量是否配置:检查环境变量是否已经设置,这可能影响资源的定位和加载。

  9. resolvePath解析构造方法传入文件路径的占位符$0:解析传入的文件路径,并替换其中的占位符。

  10. 初始化初级容器:创建DefaultListableBeanFactory实例,这是Spring容器的基础,用于管理Bean的定义和生命周期。

  11. 调用obtainBeanFactory方法:这个方法用于获取或创建Bean工厂,它是容器的核心组件。

  12. customizeBeanFactory方法:允许对Bean工厂进行定制,例如设置是否允许循环引用或覆盖。

  13. loadBeanDefinitions:加载Bean定义,这可能来自XML配置文件、注解或其他源。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐