likes
comments
collection
share

第4节 Spring容器启动源码概览

作者站长头像
站长
· 阅读数 12

一、 什么是 Spring 容器

我们通常所说的Spring容器就是 IOC容器,主要用于对所有Bean对象的管理。Spring中的 org.springframework.beans.factory.BeanFactory 就是容器的根接口。

第4节 Spring容器启动源码概览 对于BeanFactory类图,应该熟记几个关键的类,比如DefaultListableBeanFactoryConfigurableBeanFactoryConfigurableListableBeanFactoryDefaultSingletonBeanRegistry 等。

/**
 * The root interface for accessing a Spring bean container.
 * 访问Spring容器的根接口
 *
 * Bean factory implementations should support the standard bean lifecycle interfaces
 * as far as possible. The full set of initialization methods and their standard order is:
 * (一)容器启动时:BeanFactory 的实现尽可能的支持Bean的生命周期,整个Bean加载的应该遵循如下方法调用顺序:
 * 1. 如果bean实现了Aware相关接口,则调用Aware接口方法。常见的Aware接口:
 *   (1)BeanNameAware
 *   (2)BeanClassLoaderAware
 *   (3)BeanFactoryAware
 *   (4)EnvironmentAware
 *   (5)EmbeddedValueResolverAware
 *   (6)ResourceLoaderAware
 *   (7)ApplicationEventPublisherAware
 *   (8)MessageSourceAware
 *   (9)ApplicationContextAware
 *
 * 2. 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
 * 3. 调用 InitializingBean 的  afterPropertiesSet 方法
 * 4. 调用 init-method 标记的方法
 * 5. 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
 *
 * On shutdown of a bean factory, the following lifecycle methods apply:
 * (二)容器关闭时,应该依次调用如下生命周期方法
 *   1. 调用 DestructionAwareBeanPostProcessor 的 postProcessBeforeDestruction 方法
 *   2. 调用 DisposableBean 的 destroy 方法
 *   3. 调用 destroy-method 标记的方法
 */
public interface BeanFactory {
}

BeanFactory接口注释中明确了IOC容器中的Bean的生命周期流程,后续笔记中会详细说明生命周期的细节问题。

对于开发人员来讲,我们见到最多应该是org.springframework.context.ApplicationContext 接口,而不是BeanFactory,其实ApplicationContext就是BeanFactory的子接口,可以理解为它是BeanFactory的功能扩展,是一个支持更多功能的IOC容器。我们经常使用的是 ApplicationContext接口的实现类 ClassPathXmlApplicationContext

第4节 Spring容器启动源码概览

二、 Spring 容器如何启动

知道了Spring 容器就是 ApplicationContext 对象,那么容器启动流程其实就是 ApplicationContext 对象创建、初始化、使用、销毁的过程。

1. 整个IOC容器启动概览

首先我们来看这样一段代码,如下图所示: 第4节 Spring容器启动源码概览 Spring是如何完成xml文件到我们代码中bean对象的转换的呢?我想大概流程应该如下:

第4节 Spring容器启动源码概览

  • BeanDefinition是什么? 它是Spring框架的一个接口,定义了 Java bean 对象的一些信息,比如属性、构造参数等信息。
/**
 * A BeanDefinition describes a bean instance, which has property values,
 * constructor argument values, and further information supplied by
 * concrete implementations.
 */
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    // ...
}
  • 容器是如何来存放这些bean对象信息的? 在实际开发中,我们经常会做一些本地缓存,通常使用Map。那么Spring框架也是用了Map来作为存储bean对象信息的数据结构。它定义在 BeanFactory的实现类DefaultListableBeanFactory中,如下:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
    	     implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
             
    /** Map of bean definition objects, keyed by bean name */
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
    
    /** List of bean definition names, in registration order */
    private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
}
  • 初始化好的bean实例又放在哪里? 大家都知道Spring中的bean是单例模式,只会加载一次。当xml文件中配置User对象在实例化好后,它在容器中如何存放的。该问题就涉及到Spring的一级缓存,定义在 DefaultSingletonBeanRegistry 中。
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

   /** Cache of singleton objects: bean name --> bean instance
    *  Spring 中的一级缓存
    */
   private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

   /** Cache of singleton factories: bean name --> ObjectFactory
    *  Spring 中的三级缓存,用于保存 beanName 和 创建bean的工厂直接的关系
    */
   private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

   /** Cache of early singleton objects: bean name --> bean instance
    *  Spring 中的二级缓存,与一级缓存不同之处,当一个单例的bean放到这里之后,那么当bean还在创建过程中就可以通过getBean方法获取,可以方便的进行循环依赖检测
    */
   private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
}   

1.1 简单版流程图

第4节 Spring容器启动源码概览

BeanFactoryPostProcessor 和 BeanPostProcessor 的区别

  • BeanFactoryPostProcessor:可以在Bean实例化之前,对Bean的定义信息(BeanDefinition:配置元数据)进行修改。如果你配置了多个BeanFactoryPostProcessor,可通过实现Ordered接口来控制它的执行顺序

  • BeanPostProcessor:它是在Bean完成实例化和Bean属性填充之后执行,主要是对Bean的属性做一系列的修改

2. IOC容器启动源码入口

(1) 方法入口

@Test
public void testUser() {
   // 创建Spring容器
   ApplicationContext cx = new ClassPathXmlApplicationContext("application-bean.xml");
   User user = cx.getBean("user", User.class);
   System.out.printf(user.getUsername());
}

(2)ClassPathXmlApplicationContext 构造器

/**
 * 创建 ClassPathXmlApplicationContext 对象
 */
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
   this(new String[]{configLocation}, true, null);
}

/**
 * 创建Spring容器上下文
 * @param configLocations xml资源文件路径
 * @param refresh 是否刷新容器
 * @param parent 父类容器
 * @throws BeansException 容器创建失败异常
 */
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, 
                         @Nullable ApplicationContext parent) throws BeansException {
   super(parent);
   // 设置资源文件路径,比如 xml 配置文件
   setConfigLocations(configLocations);
   if (refresh) {
      refresh();
   }
}

(3)容器启动的核心方法:refresh()

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		/** Prepare this context for refreshing.
		 * 1.容器刷新前的准备工作
		 *   (1) 设置容器的启动时间
		 *   (2) 设置活跃状态为true
		 *   (3) 设置关闭状态为false
		 *   (4) 获取 Environment 对象,并加载当前系统属性值到 Environment 对象中
		 *   (5) 准备监听器和事件的集合对象,默认空集合
		 */
		prepareRefresh();
                
		/** Tell the subclass to refresh the internal bean factory.
		 *  (1) 创一个新的 BeanFactory 对象,即 DefaultListableBeanFactory 对象
		 *  (2) 该步骤中有一个很重要的逻辑就是通过 loadBeanDefinitions() 方法将所有的 BeanDefinition 对象刷新到 DefaultListableBeanFactory 中 beanDefinitionMap 属性中
		 */
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
                
		/** Prepare the bean factory for use in this context.
		 *  给容器对象 BeanFactory 的属性值赋值操作,通过一系列的add、set、ignore和register开头的方法完成赋值操作
		 */
		prepareBeanFactory(beanFactory);
		try {
			// Allows post-processing of the bean factory in context subclasses. 是一个模板方法
			postProcessBeanFactory(beanFactory);
			
                   /** Invoke factory processors registered as beans in the context.
			 *  注册 BeanFactoryPostProcessor 处理器,并调用 BeanFactoryPostProcessor 处理器的实现,可以用于扩展对 Bean 的 BeanDefinition 信息修改
			 */
			invokeBeanFactoryPostProcessors(beanFactory);
			
                   /** Register bean processors that intercept bean creation.
			 *  (1) 将Spring自带的或者用户自定义的 BeanPostProcessor 处理器到 DefaultListableBeanFactory 的 beanPostProcessors 集合属性中
			 *  (2) 可以用于扩展对实例化后的 Bean 对象属性进行修改
			 */
			registerBeanPostProcessors(beanFactory);
                        
			// Initialize message source for this context.
			// 初始化 MessageSource,用于支持国际化处理
			initMessageSource();
                        
			/** Initialize event multicaster for this context.
			 *  (1) 初始化事件广播器 ApplicationEventMulticaster
			 *  (2) 作用:将所有 ApplicationEventPublisher 发布的 ApplicationEvent 事件都广播给对应的事件侦听器
			 */
			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.
			// 完成 Spring 容器中非懒加载的单例 bean 对象的实例化。Spring Bean 初始化的核心方法。
			finishBeanFactoryInitialization(beanFactory);
                        
			// Last step: publish corresponding event.
			// 完成上下文刷新,即 ApplicationContext 的刷新工作完成
			finishRefresh();
                        
		} catch (BeansException ex) {
		
			// Destroy already created singletons to avoid dangling resources.
			// 清空容器中的单例 bean
			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. 本篇笔记只是简单的对Spring容器启动做了初步整理,后续会对其中的细节进行深入整理
  2. Spring源码中常见的接口有个初步印象,比如:
    • BeanFactory
    • Aware
    • BeanDefinition
    • BeanDefinitionReader
    • BeanFactoryPostProcessor
    • BeanPostProcessor
    • Environment
    • StandardEnvironment
    • FactoryBean