Spring4.x 笔记(6):Ioc 容器高级-内部工作机制

容器启动

Spring 的容器初始化,如new ClassPathXmlApplicationContext("spring-context.xml"),内部调用 AbstractApplicationContext 的 refresh() 方法。该方法定义了 Spring 容器在加载配置文件后的各项处理过程,即Spring 容器启动是所执行的各项操作

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
		throws BeansException {
    // 父容器
	super(parent);
	// 设置配置文件
	setConfigLocations(configLocations);
	if (refresh) {
	    // 初始化容器
		refresh();
	}
}

refresh() 方法概述

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare this context for refreshing.
		prepareRefresh();

        // 初始化 BeanFactory
		// Tell the subclass to refresh the internal bean factory.
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// Prepare the bean factory for use in this context.
		prepareBeanFactory(beanFactory);

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

            // 调用工厂后置处理器
			// Invoke factory processors registered as beans in the context.
			invokeBeanFactoryPostProcessors(beanFactory);
            
            // 注册Bean 后置处理器
			// Register bean processors that intercept bean creation.
			registerBeanPostProcessors(beanFactory);
            
            // 初始化消息源(I18n国际化)
			// Initialize message source for this context.
			initMessageSource();
            
            // 初始化应用上下文事件广播器
			// Initialize event multicaster for this context.
			initApplicationEventMulticaster();
            
            // 初始化其他特殊的 bean ,由子类实现
			// Initialize other special beans in specific context subclasses.
			onRefresh();
            
            // 注册事件监听器
			// Check for listener beans and register them.
			registerListeners();

            // 初始化所有单实例的Bean,使用懒加载模式的 Bean 除外
			// Instantiate all remaining (non-lazy-init) singletons.
			finishBeanFactoryInitialization(beanFactory);

            // 完成刷新并发布容器刷新事件
			// Last step: publish corresponding event.
			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();
		}
	}
}

步骤分析

  1. 初始化 BeanFactory。

Spring 将配置文件的信息装入 Bean定义注册表(BeanDefinitionRegistry)中,此时 Bean 还未初始化。根据配置文件,实例化 BeanFactory,在 obtainFreshBeanFactory() 方法中 ,首先调用refreshBeanFactory 方法刷新 BeanFactory,然后调用 getBeanFactory 方法获取 BeanFactory,这两个方法都是由具体的子类实现的。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	refreshBeanFactory();
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	if (logger.isDebugEnabled()) {
		logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
	}
	return beanFactory;
}
  1. 调用工厂后置处理器。

根据反射机制从 BeanDefinitionRegistry 中找出所有实现了 BeanFactoryPostProcessor 接口的 Bean,并调用其postProcessBeanFactory 方法

  1. 注册Bean 后置处理器

根据反射机制从 BeanDefinitionRegistry 中找出所有实现了 BeanFactoryPostProcessor 接口的 Bean,并将他们注册到容器 Bean 后置处理器的注册表中

  1. 初始化消息源(I18n国际化):初始化容器的国际化消息资源
  2. 初始化应用上下文事件广播器
  3. 初始化其他特殊的 bean 。由子类实现,如AbstractRefreshableWebApplicationContext 重写该方法初始化ThemeSource
  4. 注册事件监听器
  5. 初始化所有单实例的Bean,放入容器的缓存池中。使用懒加载模式的 Bean 除外。
  6. 完成刷新并发布容器刷新事件

Bean 装配流程

流程图

Spring4.x 笔记(6):Ioc 容器高级-内部工作机制

  1. ResourceLoader 加载配置文件信息,并使用 Resource 表示这个配置文件资源

  2. BeanDefinitionReader 读取 Resource 所指向的配置文件资源,解析配置文件。配置文件中每一个 解析成一个 BeanDefinition 对象,并保存在 BeanDefinitionRegistry 中

  3. 容器扫描 BeanDefinitionRegistry 中的 BeanDefinition ,使用个反射机制自动识别出 Bean 的工厂后置处理器(实现 BeanFactoryPostProcessor 接口),然后调用这个后置处理器的postProcessBeanFactory() 方法,对 BeanDefinitionRegistry 中的 BeanDefinition 进行加工处理。

  • 对使用占位符的 元素标签进行解析,得到最终的配置值
  • 对 BeanDefinitionRegistry 中的 BeanDefinition 进行扫描,通过反射扎到属性编辑器 Bean (实现了 java.beans.PropertyEditor 接口),并将其注册到容器的编辑器注册表中(PropertyEditorRegistry)
  1. Spring 容器从 BeanDefinitionRegistry 中取出加工后的 BeanDefinition,并调用 InstantiationStrategy 进行 Bean 的实例化工作

  2. 在实例化 Bean 时,Spring 容器使用 BeanWrapper 对 Bean 进行封装。BeanWrapper 提供了很多反射操作Bean的方法,将结合Bean 的 BeanDefinition 和容器中的属性编辑器,完成对 Bean 的属性注入

  3. 利用容器中的Bean 的后置处理器(实现 BeanPostProcessor 接口)对已经完成属性设置工作的 Bean 进行后续加工,完成 Bean 的装配工作

BeanDefinition:Bean 在容器中的内部表示

  1. 简单类图

Spring4.x 笔记(6):Ioc 容器高级-内部工作机制

  1. BeanDefinition 是 Bean 在容器中的内部表示。RootBeanDefinition 是最常用的实现类。如果有父子,父为 RootBeanDefinition,子为 ChildBeanDefinition;如果没有父的直接使用 RootBeanDefinition 表示

  2. Spring 容器将配置文件中的 配置信息转换为容器中的内部的 BeanDefinition 对象,并将这些 BeanDefinition 注册到 BeanDefinitionRegistry 中,后续的操作直接从 BeanDefinitionRegistry 中获取配置信息。

  3. 创建最终 BeanDefinition 主要是两个步骤:

  • 利用 BeanDefinitionReader 读取配置信息的 Resource,xml 解析成 BeanDefinition 对象。这个时候是个半成品,因为还有占位符存在
  • 利用 BeanFactoryPostProcessor 后置工厂处理器对半成品的 BeanDefinition 利用加工,生成成品的的 BeanDefinition

InstantiationStrategy:Bean 实例化策略

  1. 简单类图

Spring4.x 笔记(6):Ioc 容器高级-内部工作机制

  1. org.springframework.beans.factory.support.InstantiationStrategy 负责根据 BeanDefinition 对象创建一个 Bean 实例。相当于 new 的功能,不会参与 Bean 的属性设置工作

  2. SimpleInstantiationStrategy 是最常用的实例化策略,该策略利用 Bean 实现类的默认构造函数、带参构造函数、工厂方法创建 Bean 的示例

  3. CglibSubclassingInstantiationStrategy 扩展了 SimpleInstantiationStrategy,为需要进行方法注入的 Bean 提供支持。利用 CGLib 类库为 Bean 动态生成子类,在子类方法注入逻辑,然后使用这个动态生成的子类创建 Bean 的示例

BeanWrapper:Bean 属性编辑器填充

  1. 简单类图

Spring4.x 笔记(6):Ioc 容器高级-内部工作机制

  1. org.springframework.beans.BeanWrapper 是Spring 中的重要组件类。相当于一个代理器,Spring 委托 BeanWrapper 完成 Bean 属性的填充工作。在Bean 实例化被 InstantiationStrategy 创建出来后,容器将 Bean 实例通过 BeanWrapper 的包装起来。

  2. BeanWrapper 继承了 PropertyAccessor、PropertyEditorRegistry 接口。PropertyAccessor定义了各种访问Bean 属性的方法(getPropertyValue()),PropertyEditorRegistry 是属性编辑器的注册表。所以 BeanWrapper 的实现类 BeanWrapperImpl 具有3重身份:

  • Bean 包裹器
  • 属性访问器
  • 属性编辑器注册表
  1. BeanWrapperImpl 实例内部封装了两类组件,被封装的待处理的Bean,一套用于设置属性的属性编辑器

参考

  1. 源码地址

Spring4.x 笔记(6):Ioc 容器高级-内部工作机制