Spring 启动流程解析

95 阅读2分钟

以ClassPathXmlApplicationContext为例

1 初始化ClassPathXmlApplicationContext,设置spring相关的xml配置文件

2 调用父类AbstractApplicationContext来启动容器

  public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh,    ApplicationContext parent)
	throws BeansException {

	super(parent);
	//设置xml路径
	setConfigLocations(configLocations);
	if (refresh) {
	    //调用父类启动容器
	    refresh();
	}
}

3 启动方法

 public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare this context for refreshing.
		// 3.1 设置启动时间、状态、设置占位符熟悉资源
		prepareRefresh();

		// Tell the subclass to refresh the internal bean factory.
		// 3.2 让子类重新创建一个bean工厂
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// Prepare the bean factory for use in this context.
		// 3.3 给bean工程设置一些标准组件:如ClassLoader、BeanPostProcessor
		prepareBeanFactory(beanFactory);

		try {
			// Allows post-processing of the bean factory in context subclasses.
			// 3.4 允许子类进行对beanFactory进行处理,如注册BeanPostProcessor
			postProcessBeanFactory(beanFactory);

			// Invoke factory processors registered as beans in the context.
			// 3.5 初始化所有BeanFactoryPostProcessor类型的bean,并调用postProcessBeanFactory,运行对元数据进行修改
			invokeBeanFactoryPostProcessors(beanFactory);

			// Register bean processors that intercept bean creation.
			// 3.6 注册所有BeanPosrProccessor类型的bean到beanFactory
			registerBeanPostProcessors(beanFactory);
            
			// Initialize message source for this context.
			// 3.7 设置国际化信息
			initMessageSource();

			// Initialize event multicaster for this context.
			// 3.8 初始化消息组播器
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			// 3.9 让子类去一些初始化特殊bean
			onRefresh();

			// Check for listener beans and register them.
			// 3.10 注册ApplicationListener到时间组播器,并发布早期的事件
			registerListeners();

			// Instantiate all remaining (non-lazy-init) singletons.
			// 3.11 初始化非延时加载的单例
			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();
		}
	}
}

3.2 让子类重新创建一个bean工厂

 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    //让子类去刷新beanFactory
	refreshBeanFactory();
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	if (logger.isDebugEnabled()) {
		logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
	}
	return beanFactory;
}

ClassPathXmlApplicationContext的父类AbstractRefreshableApplicationContext refreshBeanFactory让子类去准备beanFactory的bean元数据,执行读取xml文件、解析xml、处理、注册元数据信息到BeanDefinition。

protected final void refreshBeanFactory() throws BeansException {
	if (hasBeanFactory()) {
		destroyBeans();
		closeBeanFactory();
	}
	try {
		DefaultListableBeanFactory beanFactory = createBeanFactory();
		beanFactory.setSerializationId(getId());
		customizeBeanFactory(beanFactory);
		loadBeanDefinitions(beanFactory);
		synchronized (this.beanFactoryMonitor) {
			this.beanFactory = beanFactory;
		}
	}
	catch (IOException ex) {
		throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
	}
}

而实际执行xml读取、解析、注册的是:XmlWebApplicationContext来完成。

    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
	// Create a new XmlBeanDefinitionReader for the given BeanFactory.
	XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

	// Configure the bean definition reader with this context's
	// resource loading environment.
	beanDefinitionReader.setEnvironment(getEnvironment());
	beanDefinitionReader.setResourceLoader(this);
	beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

	// Allow a subclass to provide custom initialization of the reader,
	// then proceed with actually loading the bean definitions.
	initBeanDefinitionReader(beanDefinitionReader);
	loadBeanDefinitions(beanDefinitionReader);
}