1.当Spring的IoC容器将Bean定义的资源文件封装为Spring的Resource之后,接下来要做的就是通过Spring的资源加载器(resourceLoader)读入Bean定义资源文件的过程。对于IoC容器来说,Bean定义的载入过程就是将Bean定义资源文件读入进内存并解析转换成Spring所管理的Bean的数据结构的过程。相对于SpringIoC容器定位Bean定义资源文件来说,Bean定义资源文件的载入和解析过程更复杂一些,因此按照程序的运行步骤逐条分析其实现原理。
2.以FileSystemXmlApplicationContext为例分析其载入和解析Bean定义资源文件的过程:
首先从FileSystemXmlApplicationContext的入口构造函数分析起,其代码如下:
[java]- //FileSystemXmlApplicationContext IoC容器进行初始化的入口构造函数 public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
- throws BeansException { //调用父类构造方法,为容器设置资源加载器(resourceLoader)
- super(parent); //调用父类AbstractRefreshableConfigApplicationContext的方法,设置//Bean定义的资源文件,完成IoC容器Bean定义资源的定位
- setConfigLocations(configLocations); if (refresh) {
- //调用父类AbstractApplicationContext的refresh() //函数启动载入Bean定义的过程,是Ioc容器载入Bean定义的入口
- refresh(); }
- }
Spring IoC容器对Bean定义资源的载入是从refresh()函数开始的,FileSystemXmlApplicationContext通过调用其父类AbstractApplicationContext的refresh()函数启动整个IoC容器对Bean定义的载入过程。
3.AbstractApplicationContext的refresh函数载入Bean定义过程:
[java]- public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) {
- //调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识 prepareRefresh();
- //告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从 //子类的refreshBeanFactory()方法启动
- ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //为BeanFactory配置容器特性,例如类加载器、事件处理器等
- prepareBeanFactory(beanFactory); try {
- //为容器的某些子类指定特殊的BeanPost事件处理器 postProcessBeanFactory(beanFactory);
- //调用所有注册的BeanFactoryPostProcessor的Bean invokeBeanFactoryPostProcessors(beanFactory);
- //为BeanFactory注册BeanPost事件处理器. //BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件
- registerBeanPostProcessors(beanFactory); //初始化信息源,和国际化相关.
- initMessageSource(); //初始化容器事件传播器.
- initApplicationEventMulticaster(); //调用子类的某些特殊Bean初始化方法
- onRefresh(); //为事件传播器注册事件监听器.
- registerListeners(); //初始化所有剩余的单态Bean.
- finishBeanFactoryInitialization(beanFactory); //初始化容器的生命周期事件处理器,并发布容器的生命周期事件
- finishRefresh(); }
- catch (BeansException ex) { //销毁以创建的单态Bean
- destroyBeans(); //取消refresh操作,重置容器的同步标识.
- cancelRefresh(ex); throw ex;
- } }
- }
refresh()方法主要为IoC容器Bean的生命周期管理提供条件,Spring IoC容器载入Bean定义资源文件从其子类容器的refreshBeanFactory()方法启动,所以整个refresh()中“ConfigurableListableBeanFactory beanFactory =obtainFreshBeanFactory();”这句以后代码的都是注册容器的信息源和生命周期事件,载入过程就是从这句代码启动。
AbstractApplicationContext的obtainFreshBeanFactory()方法调用子类容器的refreshBeanFactory()方法,启动容器载入Bean定义资源文件的过程,代码如下:
[java]- protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { //这里使用了委派设计模式,父类定义了抽象的refreshBeanFactory()方法,具//体实现调用子类容器的refreshBeanFactory()方法
- refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory();
- if (logger.isDebugEnabled()) { logger.debug(Bean factory for + getDisplayName() + : + beanFactory);
- } return beanFactory;
- }
4.AbstractApplicationContext子类的refreshBeanFactory()方法:
AbstractApplicationContext类中只抽象定义了refreshBeanFactory()方法,容器真正调用的是其子类AbstractRefreshableApplicationContext实现的refreshBeanFactory()方法,方法的源码如下:
[java- protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) {//如果已经有容器,销毁容器中的bean