上节咱们提到容器初始化的第一步首先进行了属性的检验,下面就要开始第二步:进行 beanFactory 的初始化工做了。java
ApplicationContext 是对 BeanFactory 的功能上的扩展,不但包含了 BeanFactory 的所有功能更在其基础上添加了大量的扩展应用,那么 obtainFreshBeanFactory 正是实现 BeanFactory ,并对配置文件进行解析。app
源代码【AbstractApplicationContext】ide
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { // 初始化 BeanFactory,并进行 XML 文件读取,并将获得的 BeanFactory 记录在当前实体的属性中 refreshBeanFactory(); // 返回当前实体的 BeanFactory 属性 ConfigurableListableBeanFactory beanFactory = getBeanFactory(); return beanFactory; }
很明显这段代码没有作什么事,将其主要的工做都委托给了 refreshBeanFactory() 方法,这个方法由其子类实现。this
源代码【AbstractRefreshableApplicationContext】code
protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { // 1. 建立 DefaultListableBeanFactory DefaultListableBeanFactory beanFactory = createBeanFactory(); // 为了序列化指定id,若是须要的话,让这个 beanFactory 从 id 反序列化到 BeanFactory 对象 beanFactory.setSerializationId(getId()); // 2. 定制 beanFactory,如设置:①是否容许同名覆盖、②是否容许循环依赖 customizeBeanFactory(beanFactory); // 3. 初始化 DocumentReader,并进行 XML 文件读取及解析 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
在 refreshBeanFactory() 方法中主要作了三件事:xml
(1) 建立 BeanFactory。建立前须要先销毁之前的 beanFactory。对象
(2) 定制 BeanFactory。设置了是否容许同名覆盖、是否容许循环依赖两个属性。你可能会奇怪,这两个属性原本就是 null,没有值,这是在干什么?仍是那名话,须要子类来覆盖。get
(3) 加载 BeanFactory 配置文件。解析 xml 文件,加载 BeanDefinition。it
protected DefaultListableBeanFactory createBeanFactory() { return new DefaultListableBeanFactory(getInternalParentBeanFactory()); }
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) { if (this.allowBeanDefinitionOverriding != null) { beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } if (this.allowCircularReferences != null) { beanFactory.setAllowCircularReferences(this.allowCircularReferences); } }
源代码【AbstractXmlApplicationContext】io
@Override protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // 1. 建立 XmlBeanDefinitionReader XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // 2. 对 beanDefinitionReader 进行环境变量的设置 beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // 3. 对 beanDefinitionReader 进行设置,默承认以覆盖 initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); } protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) { reader.setValidating(this.validating); }
在初始化了 DefaultListableBeanfactory 和 XmlBeanDefinitionReader,后就能够进行配置文件的读取了。
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { Resource[] configResources = getConfigResources(); if (configResources != null) { reader.loadBeanDefinitions(configResources); } String[] configLocations = getConfigLocations(); if (configLocations != null) { reader.loadBeanDefinitions(configLocations); } }
使用 XmlBeanDefinitionReader 的 loadBeanDefinitions 方法进行配置文件的加载机注册相信你们已经不陌生,这彻底就是开始 BeanFactory 的套路。由于在 XmlBeanDefinitionReader 中已经将以前初始化的 DefaultlistableBeanfactory 注册进去了,因此 XmlBeanDefinitionReader 所读取的 BeanDefinitionHolder 都会注册到 DefaultListableBeanfactory 中。
此时的 BeanFactory 已经解析了全部的 BeanDefinition,能够进行 bean 的加载了,不过在加载前 Spring 还作了一些其它的工做。
天天用心记录一点点。内容也许不重要,但习惯很重要!