做爲一名java工程師,沒有閱讀過spring源碼,總有一種要被鄙視的感受,另外也想經過閱讀源碼提高本身的能力,沒有比spring更合適的了。java
那麼開始這個源碼閱讀的系列吧,參考書籍《Spring源碼深度解析》spring
2019-06-26 Spring加載的解析函數
首先咱們構建的spring例子工程this
咱們主要代碼:spa
public static void main(String args[]){ BeanFactory context = new XmlBeanFactory(new ClassPathResource("ioc.xml")); Zaojiaoshu zaojiaoshu = (Zaojiaoshu) context.getBean("zaojiaoshu"); System.out.println(zaojiaoshu.getAge() + "歲" + zaojiaoshu.getHigh() + "米"); }
核心是這個XmlBeanFactory咱們來看下它的代碼,打開發現比較簡單:code
public class XmlBeanFactory extends DefaultListableBeanFactory { private final XmlBeanDefinitionReader reader; public XmlBeanFactory(Resource resource) throws BeansException { this(resource, (BeanFactory)null); } public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { super(parentBeanFactory); this.reader = new XmlBeanDefinitionReader(this); this.reader.loadBeanDefinitions(resource); } }
那麼,構造函數裏又調用了另外一個構造函數。纔是真正的核心。那麼BeanFactory自己的結構是什麼樣的?經過代碼能夠看到主要是繼承了DefaultListableBeanFactory。來看:xml
牽扯的內容不少,有些如今不能一一說明用意,只能粗略的瞭解下先。對象
好比:blog
BeanDefinitionRegistry 提供對BeanDefinition的各類增刪改查操做。後續瞭解清楚各個組建的做用後,再來添加詳細。To do ...繼承
返回以前Main方法中繼續。建立完XmlBeanFactoryBean對象時,主要參數是Resource對象。分析下:
Resource接口是spring提供的統一的資源封裝接口,用來封裝各類底層資源。
public interface Resource extends InputStreamSource { boolean exists(); boolean isReadable(); boolean isOpen(); URL getURL() throws IOException; URI getURI() throws IOException; File getFile() throws IOException; long contentLength() throws IOException; long lastModified() throws IOException; Resource createRelative(String var1) throws IOException; String getFilename(); String getDescription(); }
InputStream就更簡單了。
public interface InputStreamSource { InputStream getInputStream() throws IOException; }
獲取InputStream的返回對象。
能夠看到Resource接口裏,提供了文件是否存在/是否可讀/是否打開的方法,來判斷資源狀態。另外還提供了不一樣資源向URL/URI/File類型資源的轉換方法。
看下Resource的類圖結構:
爲了便於顯示,刪除了部分AbstractResource的實現類,主要用來看下類結構圖。
相關實現,就比較簡單了,查看源碼就能看到,好比ClassPathResource
public InputStream getInputStream() throws IOException { InputStream is; if (this.clazz != null) { is = this.clazz.getResourceAsStream(this.path); } else if (this.classLoader != null) { is = this.classLoader.getResourceAsStream(this.path); } else { is = ClassLoader.getSystemResourceAsStream(this.path); } if (is == null) { throw new FileNotFoundException(this.getDescription() + " cannot be opened because it does not exist"); } else { return is; } }
藉助ClassLoader或者class提供了底層方法進行調用。其餘的具體查看下代碼便可。核心就是可以獲取資源的InputStream流。
講了Resource,那繼續以前方法中的代碼:加載Bean。
Todo 把當時寫在word上的內容,挪過來。