IOC initialization process (5)

1 Overview

Simply put, the initialization process of the IOC container is refresh()started by a method, which means the official start of the IOC container. Specifically, this startup mainly includes the three processes of BeanDefinition Resource positioning, loading and registration.

2. IOC startup process description
  • The first process is the Resource positioning process. This Resource positioning refers to the resource positioning of BeanDefinition (for example, the various XML configurations that we usually configure in the Spring project are unified and abstracted as Resource resources), which is completed by the ResourceLoader through a unified Resource interface. This Resource Use provides a unified interface.
  • The second process is the loading process of BeanDefinition. The loading process is to represent the user-defined Bean as the data structure inside the IOC container, that is, BeanDefinition. BeanDefinition is actually the abstraction of POJO objects in the IOC container. Through the data structure defined by BeanDefinition, the IOC container can easily manage the POJO objects, that is, the Bean objects.
  • The third process is the registration process of BeanDefinition with IOC. This process is mainly achieved through the BeanDefinitionRegistry interface. The registration process is to register the BeanDefinition parsed during the loading process with the IOC container. In fact, the IOC internally injects the parsed BeanDefinition into a HashMap, and the IOC container holds these BeanDefinition data through this HashMap.
3. Source code analysis

FileSystemXmlApplicationContext as an example, the core inheritance relationship is:

FileSystemXmlApplicationContext core inheritance relationship

The sample code is:
FileSystemXmlApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:bean.xml")

When we execute the above line of code, the resource positioning, parsing, and registration process of an IOC is completed. Let's analyze the core execution flow of the above code.

/**
	 * Create a new FileSystemXmlApplicationContext, loading the definitions
	 * from the given XML file and automatically refreshing the context.
	 * @param configLocation file path
	 * @throws BeansException if context creation failed
	 */
	public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
		this(new String[] {configLocation}, true, null);
	}

The constructor we choose is to pass in a resource file path, and the internal constructor actually called is:

/**
	 * Create a new FileSystemXmlApplicationContext with the given parent,
	 * loading the definitions from the given XML files.
	 * @param configLocations array of file paths
	 * @param refresh whether to automatically refresh the context,
	 * loading all bean definitions and creating all singletons.
	 * Alternatively, call refresh manually after further configuring the context.
	 * @param parent the parent context
	 * @throws BeansException if context creation failed
	 * @see #refresh()
	 */
	public FileSystemXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {
		// 父容器设置
		super(parent);
		// 设置资源访问路径
		setConfigLocations(configLocations);
		// 刷新启动容器
		if (refresh) {
			refresh();
		}
	}

When we execute the refresh()method, our ApplicationContext advanced context container has been created, we enter the refresh()method area to view the specific execution logic:

@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.
		// 获取Beanfatory->资源的定位和解析就是在此方法中执行的
		//(1)AbstractApplicationContext#obtainFreshBeanFactory()
		//(2)AbstractApplicationContext#refreshBeanFactory()实际执行子类
		//(3)AbstractRefreshableApplicationContext#refreshBeanFactory()的方法
		创建DefaultListableBeanFactory并loadBeanDefinitions`
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// Prepare the bean factory for use in this context.
		// 配置BeanFactory标准Context特征,比如 classloader,后置处理等。
		prepareBeanFactory(beanFactory);

		try {
			// Allows post-processing of the bean factory in context subclasses.
			// 允许添加BeanFactoryProcessor来修改beanFactory,子类覆盖方法做额外处理  
			postProcessBeanFactory(beanFactory);

			// Invoke factory processors registered as beans in the context.
			// 回调 上面收集到的所有的 BeanFactoryProcessor 了
			invokeBeanFactoryPostProcessors(beanFactory);

			// Register bean processors that intercept bean creation.
			// 注册bean的处理器
			registerBeanPostProcessors(beanFactory);

			// Initialize message source for this context.
			// 国际化相关的初始化
			initMessageSource();

			// Initialize event multicaster for this context.
			// 初始化应用事件的广播
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			// 留给子类Context实现一些特殊处理的模板方法(模板方法留给子类实现)
			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();
		}
	}
}

WeChat public account

Published 41 original articles · Liked 14 · Visitors 10,000+

Guess you like

Origin blog.csdn.net/Yunwei_Zheng/article/details/105680488