Spring源码解析-IOC容器启动流程(一)

文章目录

  • 一、前言
  • 二、AnnotationConfigApplicationContext继承结构简介
  • 三、refresh()流程解析
    • 0. 核心refresh()方法源码
    • 1. prepareRefresh()
    • 2. obtainFreshBeanFactory()
      • 第一步:refreshBeanFactory()
      • 第二步. getBeanFactory()
    • 3. prepareBeanFactory(beanFactory)
    • 4. postProcessBeanFactory(beanFactory)
  • 四、预处理总结

一、前言

这篇文章是我学习spring容器创建流程的学习笔记,这个创建流程的源码解析我花了好多天来研究,文章篇幅也是比较长的。所以我将IOC容器创建流程分为三篇文章,码字不易,纯属原创。如果文章有错误之处希望大家指出!

阅读本文建议提前了解Bean的生命周期,ApplicationContext继承结构,以及工厂设计模式。

这里我就用ApplicationContext的实现类AnnotationConfigApplicationiContext来分析,使用AnnotationConfigApplicationContext可以实现基于Java的配置类(包括各种注解)加载Spring的应用上下文。避免使用application.xml进行配置。相比XML配置,更加便捷。

常用英译汉介绍:

英文 中文
BeanFactory Bean工厂
Annotation 注解
Refresh 刷新
Post 后置的
Processor 处理器
Debug 调试
Invoke 执行

了解这些常见的词汇后,看到类名、方法名和源码上的注释就可以大体猜出来干什么用的,这对阅读源码帮助很大。

二、AnnotationConfigApplicationContext继承结构简介

Spring源码解析-IOC容器启动流程(一)_第1张图片
先介绍几个相关的类或接口:

  1. BeanFactory:Bean抽象工厂的最顶层抽象接口,很多工厂类都实现这个接口。它是Spring框架的基础设施,面向Spring本身。
  2. ApplicationContext:在BeanFactory基础上定义的,实际上ApplicationContext是BeanFactory的一个超全集。面向使用Spring框架的开发者,几乎所有的应用场合都可以直接使用Application而非底层的BeanFactory。
  3. AbstractApplicationContext:是ApplicationContext最重要的一个实现类,实现了refresh()方法中的各种主要功能,也是容器创建最重要的一个方法。
  4. GenericApplicationContext:ApplicationContext的一个灵活变体实现类。

三、refresh()流程解析

测试方法创建一个AnnotationConfigApplicationContext,开启debug模式,走起!

public class Test
{
	@Test
	public void test()
	{
		ApplicationContext application = new AnnotationConfigApplicationContext(Config.class);
	}
}

接下来,就可以直接进入AnnotationConfigApplicationConfig来查看源码了。
(注意:这里的进入方法是调试功能的step into F5)

下面是AnnotationConfigApplicationContext的构造方法

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
	this();
	register(annotatedClasses);
	refresh();
}

我们要分析的核心代码,也就是Spring容器创建的核心代码,就是refresh()这个方法,进入refresh(),这个方法是AbstractApplicationContext中实现的。

0. 核心refresh()方法源码

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

		// 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);

			// Register bean processors that intercept bean creation.
			registerBeanPostProcessors(beanFactory);

			// Initialize message source for this context.
			initMessageSource();

			// Initialize event multicaster for this context.
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			onRefresh();

			// Check for listener beans and register them.
			registerListeners();

			// 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();
		}
	}
}

核心步骤是从prepareRefresh()到finishRefresh(),一共12个步骤,接下来将一一讲解。

1. prepareRefresh()

refresh前的预处理操作,进入方法

protected void prepareRefresh() {
	this.startupDate = System.currentTimeMillis(); // 计时操作
	this.closed.set(false);
	this.active.set(true);

	if (logger.isInfoEnabled()) {
		logger.info("Refreshing " + this);
	}

	// Initialize any placeholder property sources in the context environment
	initPropertySources(); // 钩子!

	// 检验属性
	getEnvironment().validateRequiredProperties(); 

	// 创建早期事件
	this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

这里主要的两个方法,一个是initPropertySources()方法,它是作为一个钩子方法,留给子类重写那种,为什么呢?

protected void initPropertySources() {
	// For subclasses: do nothing by default.
}

这个方法的内部什么都没有,所以充当了钩子。

第二个就是getEnvironment().validateRequiredProperties(),翻译下注释,意思是“验证所有标记为必需的属性都是可解析的”, 就是起一个检测属性合法的功能。

2. obtainFreshBeanFactory()

字面意思:获取BeanFactory,进入方法后:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	// 第一步
	refreshBeanFactory(); 
	// 第二步
	ConfigurableListableBeanFactory beanFactory = getBeanFactory(); 
	return beanFactory;
}

第一步:refreshBeanFactory()

这个方法是干嘛的?看起来是刷新BeanFactory的,但这时没看到BeanFactory创建呀!点进去,进入了GenericApplicationContext.class

// GenericApplicationContext.class
protected final void refreshBeanFactory() throws IllegalStateException {
	this.beanFactory.setSerializationId(getId());
}

就是给beanFactory取个id,也没啥好说的。但是有个问题:这个beanFactory在哪创建的?其实在当前类中,也就是GenericApplicationContext中,往上翻,就看到了如下代码:

public GenericApplicationContext() {
	this.beanFactory = new DefaultListableBeanFactory();
}

说明beanFactory是在GenericApplicationContext构造方法中new出来的

这时,我们已经知道这个refreshBeanFactory()看起来是刷新BeanFactory,其实是创建了一个BeanFactory

第二步. getBeanFactory()

(ps:如果你忘了obtainFreshBeanFactory的代码结构,赶紧上去看看。)
点进去后:

@Override
// GenericApplicationContext.class
public final ConfigurableListableBeanFactory getBeanFactory() {
	return this.beanFactory;
}

发现就是之前GenericApplicationContext构造方法中new出来的那个BeanFactory。

最后return beanFactory,直接把beanFactory返回了,此时的beanFactory还是个初始状态。

3. prepareBeanFactory(beanFactory)

这个方法主要是对刚刚创建出的BeanFactory的预处理操作
进入方法后:

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   // 告诉内部bean工厂使用上下文的ClassLoader等。
   beanFactory.setBeanClassLoader(getClassLoader());
   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

   // 设置各种Aware接口
   beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
   beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
   beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
   beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
   beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

   // 注册为可装配的依赖,而不是bean
   // 我们能直接在任何组件中自动注入:
   // BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
   beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
   beanFactory.registerResolvableDependency(ResourceLoader.class, this);
   beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
   beanFactory.registerResolvableDependency(ApplicationContext.class, this);

   // 注册early post-processor检测bean是否为applicationlistener。
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

   // 增加对AspectJ的支持
   if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      // 为类型匹配设置一个临时类加载器。
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }

   // 注册默认的环境beans:environment, SystemProperties, SystemEnvironment,两个System都是Map
   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());
   }
}

这个方法主要是设置Aware,注册自定义依赖和一些必要的组件,支持一些规范的功能。

4. postProcessBeanFactory(beanFactory)

BeanFactory预处理完成后的后置处理工作
点进去:

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 
{
}

里面还是空空如也…说明这是给子类重写的方法。

四、预处理总结

前四步,一直是在做一些预处理操作,主要完成的操作如下:

  1. 检验内部属性合法
  2. 创建早期事件
  3. 创建BeanFactory实例
  4. 给BeanFactory初始化
  5. 执行BeanFactory后置处理器所有操作

至此,BeanFactory已经完全操作完了,可以接受任何组件的注册了,而且它已经注册了一部分默认组件。

后续步骤分析见Spring源码解析-IOC容器启动流程(二)

你可能感兴趣的:(Spring)