Spring核心IOC原始碼解讀(一)獲取BeanFactory
在AbstractApplicationContext.refresh();的過程中,第二步為獲取BeanFactory ->obtainFreshBeanFactory()。在這個方法中,Spring先建立了BeanFactory,然後通過讀取XML配置檔案(或者掃描Java類)的方式初始化了BeanDefinition。這裡面就包括Spring Bean的主要資訊,例如依賴情況、作用域等等。
@Override public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) { // (1)Prepare this context for refreshing. prepareRefresh(); // (2)Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); ...... }
一、obtainFreshBeanFactory()方法的具體內容
/** * Tell the subclass to refresh the internal bean factory. * @return the fresh BeanFactory instance * @see #refreshBeanFactory() * @see #getBeanFactory() */ protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory();return getBeanFactory(); }
註釋上寫的:告訴子類重新整理內部的BeanFactory
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
refreshBeanFactory()、getBeanFactory()方法是抽象方法,由子類實現,這裡的子類是AbstractRefreshableApplicationContext,它是AbstractApplicationContext的子類。(類圖可以參考:大綱)
二、關鍵在於refreshBeanFactory()方法
看看AbstractRefreshableApplicationContext的實現:
@Override protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try {
//(1)初始化BeanFactory DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory);
//(2)讀取BeanFefinition loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
(1)AbstractRefreshableApplicationContext.createBeanFactory()
建立DefaultListableBeanFactory物件,這個物件的類圖關係如下
不僅實現了BeanFactory,還實現了Registry相關介面,意味著和Bean的註冊有很大關係
(2) AbstractRefreshableApplicationContext.loadBeanDefinitions()
loadBeanDefinitions()是一個抽象方法,由AbstractXmlApplicationContext實現,類圖可參考:大綱
@Override protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // (1)建立讀取Xml的物件,和BeanFactory是依賴關係 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // (2)這些都是一些初始化操作 beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // (3)真正的初始化操作發生在最後一步loadBeanDefinitions initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); }
XmlBeanDefinitionReader初始化的beanFactory物件是BeanDefinitionRegistry介面的實現
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) { super(registry); }
三、loadBeanDefinitions(beanDefinitionReader);通過Reader將XML Bean資訊讀取到BeanFactory中
BeanFactory和Reader之間的關係是依賴關係
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); } }
reader.loadBeanDefinitions(configLocations)方法中,將String型別的xml檔案地址轉為了Resource物件,下面就是通過流來讀取