加载

来源:互联网 发布:最准的掐指算法桃花 编辑:程序博客网 时间:2024/04/28 12:44

Spring IoC容器将载入的Bean定义资源文件转换为Document对象

refresh

FileSystemXmlApplicationContext通过调用其父类AbstractApplicationContext的refresh()函数启动整个IoC容器对Bean定义的载入过程:

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;             }         }     }

AbstractApplicationContext的obtainFreshBeanFactory()方法调用子类容器的refreshBeanFactory()方法,启动容器载入Bean定义资源文件的过程,代码如下:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {          //这里使用了委派设计模式,父类定义了抽象的refreshBeanFactory()方法,具体实现调用子类容器的refreshBeanFactory()方法         refreshBeanFactory();          ConfigurableListableBeanFactory beanFactory = getBeanFactory();          if (logger.isDebugEnabled()) {              logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);          }          return beanFactory;      }

AbstractApplicationContext子类的refreshBeanFactory()方法:

AbstractApplicationContext类中只抽象定义了refreshBeanFactory()方法,容器真正调用的是其子类AbstractRefreshableApplicationContext实现的 refreshBeanFactory()方法,方法的源码如下:

protected final void refreshBeanFactory() throws BeansException {         if (hasBeanFactory()) {//如果已经有容器,销毁容器中的bean,关闭容器             destroyBeans();             closeBeanFactory();         }         try {              //创建IoC容器              DefaultListableBeanFactory beanFactory = createBeanFactory();              beanFactory.setSerializationId(getId());             //对IoC容器进行定制化,如设置启动参数,开启注解的自动装配等             customizeBeanFactory(beanFactory);             //调用载入Bean定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器             loadBeanDefinitions(beanFactory);             synchronized (this.beanFactoryMonitor) {                 this.beanFactory = beanFactory;             }         }         catch (IOException ex) {             throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);         }     }

refresh()方法的作用是:在创建IoC容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在refresh之后使用的是新建立起来的IoC容器。refresh的作用类似于对IoC容器的重启,在新建立好的容器中对容器进行初始化,对Bean定义资源进行载入

loadBeanDefinitions

AbstractRefreshableApplicationContext中只定义了抽象的loadBeanDefinitions方法,容器真正调用的是其子类AbstractXmlApplicationContext对该方法的实现,AbstractXmlApplicationContext的主要源码如下:

loadBeanDefinitions方法同样是抽象方法,是由其子类实现的,也即在AbstractXmlApplicationContext中。

public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {      ……      //实现父类抽象的载入Bean定义方法      @Override      protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {          //创建XmlBeanDefinitionReader,即创建Bean读取器,并通过回调设置到容器中去,容  器使用该读取器读取Bean定义资源          XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);          //为Bean读取器设置Spring资源加载器,AbstractXmlApplicationContext的          //祖先父类AbstractApplicationContext继承DefaultResourceLoader,因此,容器本身也是一个资源加载器         beanDefinitionReader.setResourceLoader(this);         //为Bean读取器设置SAX xml解析器         beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));         //当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制         initBeanDefinitionReader(beanDefinitionReader);         //Bean读取器真正实现加载的方法         loadBeanDefinitions(beanDefinitionReader);     }     //Xml Bean读取器加载Bean定义资源     protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {         //获取Bean定义资源的定位         Resource[] configResources = getConfigResources();         if (configResources != null) {             //Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位             //的Bean定义资源             reader.loadBeanDefinitions(configResources);         }         //如果子类中获取的Bean定义资源定位为空,则获取FileSystemXmlApplicationContext构造方法中setConfigLocations方法设置的资源         String[] configLocations = getConfigLocations();         if (configLocations != null) {             //Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位             //的Bean定义资源             reader.loadBeanDefinitions(configLocations);         }     }     //这里又使用了一个委托模式,调用子类的获取Bean定义资源定位的方法     //该方法在ClassPathXmlApplicationContext中进行实现,对于我们     //举例分析源码的FileSystemXmlApplicationContext没有使用该方法     protected Resource[] getConfigResources() {         return null;     }   ……  41}