(Spring源码解析)一步一步分析,springMVC项目启动过程(二)

 这篇来看下AbstractApplicationContext中的refresh()方法,这个方法初始化且启动整个spring容器的核心。方法名字理解起来就是刷新的意思,意味着刷新整个Spring容器,做好一切准备。

public void refresh() throws BeansException, IllegalStateException {
	    //初始化容器需要加锁,防止并发加载,startupShutdownMonitor锁对象
		synchronized (this.startupShutdownMonitor) {
			// 预加载刷新,里面包含初始化准备工作
			prepareRefresh();

			// 创建bean工厂,加载初始化beanDefinitionMap、依赖关系、注入属性等等对象,注入对象解析的实现在里面
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 准备beanFactory绑定到context容器
			prepareBeanFactory(beanFactory);

			try {
				// 允许在context子类中对bean工厂进行后处理
				postProcessBeanFactory(beanFactory);

				// 实例化并调用所有已注册的beanfactorypostprocessor bean对象
				invokeBeanFactoryPostProcessors(beanFactory);

				// 注册拦截bean创建的bean处理器.
				registerBeanPostProcessors(beanFactory);

				// 初始化国际化消息资源
				initMessageSource();

				// 初始化应用事件广播器,用来触发事件监听
				initApplicationEventMulticaster();

				// 初始化context子类的特殊bean对象
				onRefresh();

				// 注册监听器和事件类型,就是把所有对应的监听器和事件类型保存到应用容器里
				registerListeners();

				// 实例化所有剩下的(非惰性初始化)单例.
				finishBeanFactoryInitialization(beanFactory);

				// 最后一步:发布刷新完毕相应的事件ContextRefreshedEvent
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// 出现刷新异常,则销毁已经创建的单例以避免占用资源。
				destroyBeans();

				// 重置激活标志
				cancelRefresh(ex);

				// 抛出异常
				throw ex;
			}

			finally {
				// 清楚部分加载解析用到的beanmeta缓存,因为我们已经在spring核心容器里重置了常见的内部缓存 可能不再需要单身bean的元数据了
				resetCommonCaches();
			}
		}
	}

咋一看这个方法的代码很少,其实里面调用很多层框架所需要的实现,(初略总结)大概做了如下事情:

加载PropertySources、环境参数、初始化并构建BeanFactory、解析注册XmlBeanDefinition,初始化创建装载bean、解析Bean之间的依赖关系、国际化消息初始化、初始化监听事件广播、注册所有监听器、事件发布通知结束等。

预加载方法:

protected void prepareRefresh() {
		this.startupDate = System.currentTimeMillis();//记录启动时间
		this.closed.set(false);//容器没有关闭标识
		this.active.set(true);//容器启动激活标识

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

		// 初始化加载系统上下文环境属性参数资源,在ContextLoader可能已加载
		initPropertySources();

		// 校验所有的设置Required的Properties,在ConfigurablePropertyResolver#setRequiredProperties设置
		getEnvironment().validateRequiredProperties();

		// 初始化容器早期事件Set集合
		this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

本章重点分析BeanFactory初始化过程:

  1. 预准备 初始化环境property sources
  2. 初始化BeanFactory,解析xml注册配置和bean对象
  3. 创建并刷新BeanFactory,解析注册Bean
	AbstractRefreshableApplicationContext#refreshBeanFactory方法实现
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();//创建BeanFactory对象
			beanFactory.setSerializationId(getId());//序列化id
			customizeBeanFactory(beanFactory);//
			loadBeanDefinitions(beanFactory);//加载资源解析BeanDefinition
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

可以看到refreshBeanFactory中的方法loadBeanDefinitions加载资源并去解析xml,然后创建BeanDefinition等操作

XmlWebApplicationContext的具体实现loadBeanDefinitions方法,第一个参数location就是web.xml配置的configLocations路径,第二参数actualResources的资源Set

public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
		ResourceLoader resourceLoader = getResourceLoader();
		if (resourceLoader == null) {
			throw new BeanDefinitionStoreException(
					"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
		}

		if (resourceLoader instanceof ResourcePatternResolver) {
			// Resource pattern matching available.
			try {
				Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
				int loadCount = loadBeanDefinitions(resources);
				if (actualResources != null) {
					for (Resource resource : resources) {
						actualResources.add(resource);
					}
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
				}
				return loadCount;
			}
			catch (IOException ex) {
				throw new BeanDefinitionStoreException(
						"Could not resolve bean definition resource pattern [" + location + "]", ex);
			}
		}
		else {
			// Can only load single resources by absolute URL.
			Resource resource = resourceLoader.getResource(location);
			int loadCount = loadBeanDefinitions(resource);
			if (actualResources != null) {
				actualResources.add(resource);
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
			}
			return loadCount;
		}
	}

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/lq0645321/article/details/79417920
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞