上節咱們提到容器初始化的第一步首先進行了屬性的檢驗,下面就要開始第二步:進行 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 還作了一些其它的工做。
天天用心記錄一點點。內容也許不重要,但習慣很重要!