@SpringBootApplication public class Application { public static void main(String[] args) { // 手動啓用一個ioc容器 FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("src/main/resources/spring-bean.xml"); } }
FileSystemXmlApplicationContext的源碼以下:java
public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext { public FileSystemXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { super(parent); // 設置xml配置信息的所在位置 setConfigLocations(configLocations); if (refresh) { // ioc容器啓動的方法 refresh(); } } }
能夠看出refresh()的完成就是標誌着ioc容器的啓動完成,起詳細源碼以下:spring
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. // 刷新前的處理,好比標註環境啓動時間,標註環境啓動標識active = true, 標註環境關閉標識close = false 等 // active標識和close標識用atomic修飾,保持原子性 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. // 獲取一個新的,乾淨的容器 // 先調用refreshBeanFactory()方法 // 刪除舊的容器,而後建立一個新的容器而且初始化等,最後返回這個新的容器 // 在refreshBeanFactory方法中,載入BeanDefinition信息 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. // 配置容器的標準環境屬性,好比context的classLoader或者poseProcessor這些 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. // 配置容器的後置處理 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. // 調用BeanFactory的後處理器 invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. // 註冊Bean的後處理器,在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. // 初始化一些特殊的bean onRefresh(); // Check for listener beans and register them. // 檢查監聽bean而且註冊到容器中 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. // 初始化全部非懶加載的bean 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(); } } }
BeanDefinition的載入是在ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()處完成的,在obtainFreshBeanFactory()方法裏,會先refreshBeanFactory(),源碼以下:數據結構
protected final void refreshBeanFactory() throws BeansException { // 若是有beanFactory 指的是否持有defaultListableBeanFactory if (hasBeanFactory()) { // 銷燬容器裏面的全部singleton bean // 源碼其實容器裏面把bean以及bean的信息等都放入hashMap或者ConCurrentHashMap裏面,而後把這些map clear一下 destroyBeans(); // 關閉容器 // 將容器持有的DefaultListableBeanFactory設置成null closeBeanFactory(); } try { // new 一個新的defaultListableBeanFactory DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); // 定製容器 設置容器的一些屬性 customizeBeanFactory(beanFactory); // 設置definitionReader、resourceLoader、entityResolver等,方面後序對於BeanDefinition的處理 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
先判斷是否已經存在容器,若是已經存在,則先銷燬容器裏面的單例bean,而後再關閉容器。後序重新建立一個DefaultListableBeanFactory,而後設置好一些相應的屬性以後,則會開始loadBeanDefinitionside
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // Configure the bean definition reader with this context's // resource loading environment. beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // Allow a subclass to provide custom initialization of the reader, // then proceed with actually loading the bean definitions. initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); }
先定義一個XmlBeanDefinitionReader,用來讀BeanDefinition是以xml形式來保存的元數據,類型的若是bean是用註解的形式的話,則也有相應的AnnotatedBeanDefinitionReader,給容器設置好相應的閱讀器以後post
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { // resource就是配置的信息源,有多是一個bean.xml,也有多是一個註解的config類 Resource[] configResources = getConfigResources(); if (configResources != null) { reader.loadBeanDefinitions(configResources); } String[] configLocations = getConfigLocations(); if (configLocations != null) { reader.loadBeanDefinitions(configLocations); } }
在一系列對resource包裝以後,執行:this
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { Document doc = doLoadDocument(inputSource, resource); return registerBeanDefinitions(doc, resource); } // 如下省略 }
此處纔是真正的開始加載beanDefinition,會先把信息處理成標準的document,而後調用能夠閱讀document的BeanDefinitionDocumentReader繼續解析信息源,最後就是將信息源解析成spring統一的一個beanDefinition數據結構,而後放入一個BeanDefinitionHolder,最後在push到容器內維護好的一個hashMap裏面。其實就是整個beanDefinition的載入就是將不一樣信息源的解析成ioc標準的數據結構,而後放入到容器的map裏面atom