Spring 源码分析(一)了解Spring容器的刷新逻辑

865 阅读5分钟

想来对于任何以为 java 开发人员,Spring 都是一个不会陌生的框架,但是如果你需要真正的去了解它的实现以及运行原理,就离不开对 Spring 源码的分析与思考。

下载源码

源码下载查看可见:查看 spring 源码

了解 Spring 容器的刷新逻辑,即为探究 AbstractApplicationContext#refresh() 方法都做了什么。 该方法是 Spring Bean 加载的核心,定义了整个 Spring 上下文加载的流程。

本篇文章我们就根据 refresh 中各个方法来分析整个 Spring 容器的刷新逻辑。

refresh方法

  • preareRefresh 刷新前的工作准备
  • obtainFreshBeanFactory 获取子类刷新后的内部beanFactory实例
  • prepareBeanFactory 为容器注册必要的系统级别的Bean
  • postProcessBeanFactory 允许容器的子类去注册postProcessor
  • invokeBeanFactoryPostProcessors 调用容器注册的容器级别的后置处理器
  • registerBeanPostProcessors 向容器注册Bean级别的后置处理器
  • initMessageSource 初始化国际化配置
  • initApplicationEventMulticaster 初始化事件发布者组件
  • onRefresh 在单例Bean初始化之前预留给子类初始化其他特殊bean的口子
  • registerListeners 向前面的事件发布者组件注册事件监听者
  • finishBeanFactoryInitialization 设置系统级别的服务,实例化所有非懒加载的单例
  • finishRefresh 触发初始化完成的回调方法,并发布容器刷新完成的事件给监听者
  • resetCommonCaches 重置Spring内核中的共用缓存

好,让我们来分析 refresh 方法

@Override
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
            // 准备此上下文來进行刷新。状态值的更新
            prepareRefresh();
		
            // 告诉子类刷新内部 bean 工厂。本章节只分析 beanFactory 的创建
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
		
            // 注册一些容器中需要的系统 bean 例如:classLoader 等
            prepareBeanFactory(beanFactory);
        
            try {
		// 允许容器的子类去注册 postProcessor,钩子方法
		postProcessBeanFactory(beanFactory);
			
                // 激活在容器中注册为 bean 的 BeanFactoryPostProcessors
		// 扫描应用中所有 BeanDefinition 并注册到容器之中
		invokeBeanFactoryPostProcessors(beanFactory);
			
                // 注册拦截 bean 创建过程的 BeanPostProcessor
		registerBeanPostProcessors(beanFactory);
			
                // 给 ApplicationContext 提供消息源
		initMessageSource();
			
                // 初始化 ApplicationEventMulticaster 该类作为事件发布者,
		// 可以存储所有事件监听者信息,并根据不同的事件,通知不同的事件监听者。
		initApplicationEventMulticaster();
			
                // 预留给 AbstractApplicationContext 的子类用于初始化其他特殊的 bean,
		// 该方法需要在所有单例 bean 初始化之前调用
		// 比如 Web 容器就会去初始化一些和主题展示相关的 Bean(ThemeSource)
		onRefresh();
			
                // 注册监听器(检查监听器的 bean 并注册它们)
		registerListeners();
			
                // 设置自定义的类型转化器 ConversionService,
		// 设置自定义 AOP 相关的类 LoadTimeWeaverAware,
		// 清除临时的 ClassLoader
		// 实例化所有的类(懒加载的类除外)
		finishBeanFactoryInitialization(beanFactory);
			
                // 初始化容器的生命周期事件处理器,(默认使用 DefaultLifecycleProcessor),调用扩展了 SmartLifecycle 接口的 start 方法
		// 当 Spring 容器加载所有 bean 并完成初始化之后,会接着回调实现该接口的类中对应的方法(start 方法)
		// 与 发布容器刷新完毕事件 ContextRefreshedEvent 给对应的事件监听者
		finishRefresh();
			} 
        // ··· catch 
	}
}

refresh 方法

一、preareRefresh 刷新前的工作准备

容器的准备预处理:记录spring容器的启动时间startupDate, 标记容器为激活,初始化上下文环境如文件路径信息,验证必填属性是否填写。

protected void prepareRefresh() {
	// Switch to active.
	this.startupDate = System.currentTimeMillis();
	this.closed.set(false);
	// 1.设置容器的状态为激活
	this.active.set(true);
	//··· logger
	
        // 2.初始化 Environment 的 propertySources 属性
	//样例<context:property-placeholder location="classpath*:/config/load.properties"/>
	initPropertySources();
	
        // 3.校验 Environment 的 requiredProperties 是否都存在
	// 请参考 ConfigurablePropertyResolver#setRequiredProperties
	getEnvironment().validateRequiredProperties();
    
	// Store pre-refresh ApplicationListeners...
    
	// 4.创建事件集合
	this.earlyApplicationEvents = new LinkedHashSet<>();
}

二、obtainFreshBeanFactory 获取子类刷新后的内部beanFactory实例

获取到 xml 中 bean 标签里配置的各种属性,封装成一个 BeanDefinition 对象,然后把这个对象存到我们 IOC 容器的 beanDefinitionMap、beanDefinitionNames 中,为之后在 IOC 容器中使用与获取创造条件,即完成 ConfigurableListableBeanFactory 的创建。

该方法在 《Spring源码分析(二)BeanFactory 的创建与xml 配置的解析》中仔细分析。 ​

三、prepareBeanFactory 为容器注册必要的系统级别的Bean

可以看到,在 beanFactory 创建完成后,代码继续注册一些容器中需要的系统 bean 例如:classLoader 等。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	// 设置 beanFactory 使用容器的类加载器
	beanFactory.setBeanClassLoader(getClassLoader());
	// 设置 beanFactory 的表达式语言处理器
        // Spring3 开始增加了对语言表达式的支持,默认可以使用#{bean.xxx}的形式来调用相关属性值
	beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
	// 为 beanFactory 增加一个默认的 propertyEditor
	beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
	// 添加该处理器的作用:当应用程序定义的 Bean 实现 ApplicationContextAware 接口时注入 ApplicationContext 对象
	beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
	// 如果某个 bean 依赖于以下几个接口的实现类,在自动装配的时候忽略它们,
	// Spring 会通过其他方式来处理这些依赖。
	beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
	beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
	beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
	beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
	beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
	beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

	// 修正依赖,这里是注册一些自动装配的特殊规则,比如是 BeanFactory class接口的实现类,则在运行时修正指定为当前 BeanFactory
	beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
	beanFactory.registerResolvableDependency(ResourceLoader.class, this);
	beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
	beanFactory.registerResolvableDependency(ApplicationContext.class, this);

	// 注册早期后置处理器,用于检测内部 bean 作为应用程序监听器
	// ApplicationListenerDetector 的作用就是判断某个 Bean 是否是 ApplicationListener,
	// 如果是,加入到事件监听者队列。
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

	// 如果找到一个 LoadTimeWeaver,那么就准备将后置处理器添加至 beanFactory
	if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
		beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
		// 为类型匹配设置临时类加载器.
		beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
	}

	// 注册默认 environment 环境
	if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
		beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
	}
	if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
		beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
	}
	if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
		beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
	}
}

四、postProcessBeanFactory 允许容器的子类去注册postProcessor

之后 Spring 允许容器的子类去注册 postProcessor,这是 Spring 预留给子类去实现的方法。

五、invokeBeanFactoryPostProcessors 调用容器注册的容器级别的后置处理器

在 invokeBeanFactoryPostProcessors 方法中,我们把具体实现逻辑代理给了 PostProcessorRegistrationDelegate 来处理,这里其实就是把注册 PostProcessor 的调用逻辑聚合到一个类里,我们继续跟进看看:

public static void invokeBeanFactoryPostProcessors(
		ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

	// 如果有BeanDefinitionRegistryPostProcessor的话优先执行
	Set<String> processedBeans = new HashSet<>();
	//如果是BeanDefinitionRegistry类型的话
	if (beanFactory instanceof BeanDefinitionRegistry) {
		BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
		// 用于记录常规 BeanFactoryPostProcessor
		List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
		// 用于记录 BeanDefinitionRegistryPostProcessor
		List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
		// 遍历所有参数传递进来的 BeanFactoryPostProcessor(它们并没有作为bean注册在容器中)
		// 将所有参数传入的 BeanFactoryPostProcessor 分成两组 :
		// BeanDefinitionRegistryPostProcessor 和常规 BeanFactoryPostProcessor
		// 1.如果是 BeanDefinitionRegistryPostProcessor,现在执行 postProcessBeanDefinitionRegistry(),
		// 2.否则记录为一个常规 BeanFactoryPostProcessor,暂时不执行处理
		for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
			if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
				BeanDefinitionRegistryPostProcessor registryProcessor =
						(BeanDefinitionRegistryPostProcessor) postProcessor;
				registryProcessor.postProcessBeanDefinitionRegistry(registry);
				registryProcessors.add(registryProcessor);
			}
			else {
				regularPostProcessors.add(postProcessor);
			}
		}

                //用于记录当前正要被执行的BeanDefinitionRegistryPostProcessor
		List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
		// 首先, 对 实现了优先级顺序接口的Bean形式 BeanDefinitionRegistryPostProcessor进行调用
		// 找出所有容器中注册为BeanDefinitionRegistryPostProcessor的postProcessor名字数组
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
		for (String ppName : postProcessorNames) {
			//遍历容器,将BeanDefinitionRegistryPostProcessor类型的后置处理器Bean实例给添加到当前的注册处理器中
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				processedBeans.add(ppName);
			}
		}
		//根据优先级排序
		sortPostProcessors(currentRegistryProcessors, beanFactory);
		registryProcessors.addAll(currentRegistryProcessors);
		//按顺序执行BeanDefinitionRegistryPostProcessors
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
		currentRegistryProcessors.clear();
		// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
		//其次对实现了Ordered接口的BeanDefinitionRegistryPostProcessors进行调用
		postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
		for (String ppName : postProcessorNames) {
			if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				processedBeans.add(ppName);
			}
		}
		//按照Order排序
		sortPostProcessors(currentRegistryProcessors, beanFactory);
		//将排完序的BeanDefinitionRegistry
		registryProcessors.addAll(currentRegistryProcessors);
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
		currentRegistryProcessors.clear();
		// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
		//最后,执行剩下的BeanDefinitionRegistryPostProcessors
		boolean reiterate = true;
		while (reiterate) {
			reiterate = false;
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
					reiterate = true;
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();
		}
		// 因为BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor,所以这里
		// 也对所有 BeanDefinitionRegistryPostProcessor 调用其方法 postProcessBeanFactory()
		invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
		// 对所有常规 BeanFactoryPostProcessor 调用其方法 postProcessBeanFactory()
		invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
	}
	else {
		//如果都是常规的BeanFactoryPostProcessor,则调用其方法 postProcessBeanFactory()
		invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
	}
	// 上面逻辑执行了以参数形式传入的BeanDefinitionRegistryPostProcessor以及常规的BeanFactoryPostProcessor
	// 也执行了容器里面的BeanDefinitionRegistryPostProcessor,故还剩下容器里面的BeanFactoryPostProcessor需要去处理
	// 逻辑是一样的,也分为实现了PriorityOrdered和Ordered以及两个都没实现的
	// ···
}

详情可了解系列文章 注解的全链路解析

六、registerBeanPostProcessors 向容器注册Bean级别的后置处理器

允许容器的子类去注册postProcessor,钩子方法 方便后续调用 getBean 方法去创建 bean 实例的时候对后置处理器的处理

七、initMessageSource 初始化国际化配置

一些国际化相关的配置,如果在此上下文中未定义国际化资源,则使用父上下文的国际化资源。

protected void initMessageSource() {
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
		this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
		// 使用此上下文的 MessageSource 知道父上下文的 MessageSource.
		if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
			HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
			if (hms.getParentMessageSource() == null) {
				// 如果没有已注册的父 MessageSource,则只将父上下文设置为父 MessageSource
				// registered already.
				hms.setParentMessageSource(getInternalParentMessageSource());
			}
		}
		if (logger.isTraceEnabled()) {
			logger.trace("Using MessageSource [" + this.messageSource + "]");
		}
	}
	else {
		// 使用空 MessageSource 可以接受 getMessage 方法的调用
		DelegatingMessageSource dms = new DelegatingMessageSource();
		dms.setParentMessageSource(getInternalParentMessageSource());
		this.messageSource = dms;
		beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
		if (logger.isTraceEnabled()) {
			logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
		}
	}
}

八、initApplicationEventMulticaster 初始化事件发布者组件

初始化 ApplicationEventMulticaster 该类 作为事件发布者 可以存储所有事件监听者信息,并根据不同的事件,通知不同的事件监听者

protected void initApplicationEventMulticaster() {
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	// 如果容器存在 ApplicationEventMulticaster 的 bean 实例,
        // 则赋值给容器的 applicationEventMulticaster
	if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
		this.applicationEventMulticaster =
				beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
		if (logger.isTraceEnabled()) {
			logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
		}
	}
	else {
		// 没有则新建一个 SimpleApplicationEventMulticaster,
		// 并完成对 SimpleApplicationEventMulticaster Bean 的注册
		this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
		beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
		if (logger.isTraceEnabled()) {
			logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
					"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
		}
	}
}

九、onRefresh 在单例Bean初始化之前预留给子类初始化其他特殊bean的口子

模板方法,可以重写以添加特定于上下文的刷新工作。 例如:StaticWebApplicationContext#onRefresh() 初始化主题的用途 该方法在特殊实例实例化(finishBeanFactoryInitialization)之前调用特殊bean的初始化。 ​

十、registerListeners 向前面的事件发布者组件注册事件监听者

添加应用程序监听器作为监听器的 bean。 如果不影响其他监听器,可以在没有 bean 的情况下添加。

protected void registerListeners() {
	// 首先注册静态的指定的监听器
	for (ApplicationListener<?> listener : getApplicationListeners()) {
		getApplicationEventMulticaster().addApplicationListener(listener);
	}
    
	// 不要在这里初始化 factorybean 我们需要保留所有未初始化的常规 bean(事件监听器),
	// 让后处理器应用到它们!
	String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
	for (String listenerBeanName : listenerBeanNames) {
		getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
	}
    
	// 至此,已经完成将监听器注册到 ApplicationEventMulticaster 中,
	// 现在我们最终拥有一个多路广播器来发布前期的应用程序事件给监听器.
	Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
	this.earlyApplicationEvents = null;
	if (earlyEventsToProcess != null) {
		for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
			getApplicationEventMulticaster().multicastEvent(earlyEvent);
		}
	}
}

十一、finishBeanFactoryInitialization 设置系统级别的服务,实例化所有非懒加载的单例

完成此上下文的 beanFactory 的初始化,初始化所有剩余的单例 bean。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
	// 初始化此容器的转换器
	// 转换器的职责是处理通过配置给 bean 实例成员变量赋值的时候的类型转换工作
	if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
			beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
		beanFactory.setConversionService(
				beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
	}

	// 如果没有注册过 bean 后置处理器 postProcessor,则注册默认的解析器
	// (例如主要用于解析 properties 文件的 PropertyPlaceholderConfigurer )
	// @value 注解或在 xml 中使用 ${} 的方式进行环境相关的配置
	if (!beanFactory.hasEmbeddedValueResolver()) {
		beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
	}

	// AOP 分为三种方式:编译期织入、类加载期织入和运行期织入
	// LoadTimeWeaving 属于第二种,主要通过 JVM 进行织入
	// 先初始化 LoadTimeWeaverAware bean,以便尽早注册它们的 transformers
	String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
	for (String weaverAwareName : weaverAwareNames) {
		getBean(weaverAwareName);
	}

	// 停止使用临时类加载器进行类型匹配.
	beanFactory.setTempClassLoader(null);

	// 冻结配置,允许缓存所有 bean 定义元数据,不希望有进一步的更改
	beanFactory.freezeConfiguration();

	// 实例化所有剩余的(non-lazy-init 非延时加载的)单例
	beanFactory.preInstantiateSingletons();
}

十二、finishRefresh 触发初始化完成的回调方法,并发布容器刷新完成的事件给监听者

当 Spring 容器加载所有 bean 并完成初始化之后,会接着回调实现该接口的类中对应的方法(start() 方法) 并发布容器刷新完毕事件 ContextRefreshedEvent 给对应的事件监听者

protected void finishRefresh() {	
    // 清除上下文级别的资源缓存(如扫描的 ASM 元数据)	
    clearResourceCaches();    	
    // 为这个上下文初始化生命周期处理器	
    initLifecycleProcessor();    	
    // 首先将刷新传播到生命周期处理器	
    getLifecycleProcessor().onRefresh();    	
    // 发布最终事件	
    publishEvent(new ContextRefreshedEvent(this));    	
    // 如果处于激活状态,将参与到 LiveBeansView MBean 中.	
    LiveBeansView.registerApplicationContext(this);
}

十三、resetCommonCaches 重置Spring内核中的共用缓存

重置 Spring 的共同的反射元数据缓存,特别是 ReflectionUtils, AnnotationUtils, ResolvableType 和 CachedIntrospectionResults 缓存。

protected void resetCommonCaches() {	
    ReflectionUtils.clearCache();	
    AnnotationUtils.clearCache();	
    ResolvableType.clearCache();	
    CachedIntrospectionResults.clearClassLoader(getClassLoader());
}

总结

总结来说,Spring 容器的刷新逻辑主要在AbstractApplicationContext#refresh()方法, 简短来说该方法就是把beanFactory清空为初始状态,再按照应用程序的意图填满各种bean实例。

本文基于 spring-framework 5.2.10.RELEASE 版本进行分析