IOC初期化プロセス(5)

1.概要

簡単に言えば、IOCコンテナーの初期化プロセスはrefresh()メソッドによって開始されます。つまり、IOCコンテナーの正式な開始です。具体的には、このスタートアップには、主にBeanDefinitionリソースの配置、ロード、および登録の3つのプロセスが含まれます。

2. IOC起動プロセスの説明
  • 最初のプロセスは、リソース配置プロセスです。このリソース配置は、BeanDefinitionのリソース配置を指します(たとえば、Springプロジェクトで通常構成するさまざまなXML構成は、リソースリソースとして統合および抽象化されます)。これは、統合されたResourceインターフェースを介してResourceLoaderによって実行されます。使用により、統一されたインターフェースが提供されます。
  • 2番目のプロセスは、BeanDefinitionのロードプロセスです。ロードプロセスでは、ユーザー定義のBeanをIOCコンテナ内のデータ構造、つまりBeanDefinitionとして表します。BeanDefinitionは、実際にはIOCコンテナ内のPOJOオブジェクトを抽象化したものであり、BeanDefinitionによって定義されたデータ構造を通じて、IOCコンテナはPOJOオブジェクト、つまりBeanオブジェクトを簡単に管理できます。
  • 3番目のプロセスは、IOCでのBeanDefinitionの登録プロセスです。このプロセスは、主にBeanDefinitionRegistryインターフェースを介して実現されます。登録プロセスは、ロードプロセス中に解析されたBeanDefinitionをIOCコンテナに登録することです。実際、IOCは内部的に解析されたBeanDefinitionをHashMapに注入し、IOCコンテナはこのHashMapを通じてこれらのBeanDefinitionデータを保持します。
3.ソースコード分析

FileSystemXmlApplicationContextを例にすると、コアとなる継承関係は次のとおりです。

FileSystemXmlApplicationContextコアの継承関係

サンプルコードは次のとおりです。
FileSystemXmlApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:bean.xml")

上記のコード行を実行すると、IOCのリソースの配置、解析、および登録プロセスが完了するので、上記のコードのコア実行フローを分析してみましょう。

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

私たちが選択するコンストラクタは、リソースファイルパスを渡すことです。実際に呼び出される内部コンストラクタは次のとおりです。

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

refresh()メソッドを実行すると、ApplicationContextアドバンストコンテキストコンテナーが作成され、refresh()メソッド領域に入って特定の実行ロジックを表示します。

@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パブリックアカウント

公開された41元の記事 ウォン称賛14 ビュー10000 +

おすすめ

転載: blog.csdn.net/Yunwei_Zheng/article/details/105680488