Proceso de inicialización del COI (5)

1. Descripción general

En pocas palabras, el proceso de inicialización del contenedor IOC se refresh()inicia mediante un método, lo que significa el inicio oficial del contenedor IOC. Específicamente, esta startup incluye principalmente los tres procesos de posicionamiento, carga y registro de BeanDefinition Resource.

2. Descripción del proceso de inicio del COI
  • El primer proceso es el proceso de posicionamiento de recursos. Este posicionamiento de recursos se refiere al posicionamiento de recursos de BeanDefinition (por ejemplo, las diversas configuraciones XML que habitualmente configuramos en el proyecto Spring están unificadas y resumidas como recursos de recursos), que ResourceLoader completa a través de una interfaz de recursos unificada. El uso proporciona una interfaz unificada.
  • El segundo proceso es el proceso de carga de BeanDefinition. El proceso de carga es representar el Bean definido por el usuario como la estructura de datos dentro del contenedor IOC, es decir, BeanDefinition. BeanDefinition es en realidad la abstracción de objetos POJO en el contenedor IOC. A través de la estructura de datos definida por BeanDefinition, el contenedor IOC puede gestionar fácilmente los objetos POJO, es decir, los objetos Bean.
  • El tercer proceso es el proceso de registro de BeanDefinition con IOC. Este proceso se logra principalmente a través de la interfaz BeanDefinitionRegistry. El proceso de registro es registrar el BeanDefinition analizado durante el proceso de carga con el contenedor IOC. De hecho, el IOC inyecta internamente la BeanDefinition analizada en un HashMap, y el contenedor IOC contiene estos datos de BeanDefinition a través de este HashMap.
3. Análisis del código fuente

FileSystemXmlApplicationContext como ejemplo, la relación de herencia central es:

FileSystemXmlApplicationContext relación de herencia central

El código de muestra es:
FileSystemXmlApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:bean.xml")

Cuando ejecutamos la línea de código anterior, se completa el proceso de posicionamiento de recursos, análisis y registro de un COI. Analicemos el flujo de ejecución central del código anterior.

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

El constructor que elegimos es pasar una ruta de archivo de recursos, y el constructor interno realmente llamado es:

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

Cuando ejecutamos el refresh()método, se ha creado nuestro contenedor de contexto avanzado ApplicationContext, ingresamos al refresh()área del método para ver la lógica de ejecución específica:

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

Cuenta pública WeChat

41 artículos originales publicados · Me gustaron 14 · Visitantes más de 10,000

Supongo que te gusta

Origin blog.csdn.net/Yunwei_Zheng/article/details/105680488
Recomendado
Clasificación