Spring技術內幕筆記2--我懶不寫了哈哈哈哈。

西伯利亞愛學習的狼發表於2021-10-03

再次閱讀這本書有些不一樣的感悟,記錄一些零星點點。

1.1 關於IOC容器設計的線路區別

我們都知道在Spring裡主要有兩種設計IOC容器的思路,一種是圍繞BeanFactory,另外一種是圍繞ApplicationContext展開。這兩種設計的主要區別在哪裡?
從頭回憶一下兩種設計方案的實現

1.1.1 BeanFactory

以下是BeanFactory介面:

處於IOC頂層的設計介面BeanFactory只提供了一些基本的方法,getBean(),containsBean(),isSingleton()等等。
我們以XmlBeanFactory為例子展示建立它的過程:
首先是一張UML圖:
建構函式

public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
       super(parentBeanFactory);
       this.reader = new XmlBeanDefinitionReader(this);
       this.reader.loadBeanDefinitions(resource);
   }

可以看出建立以BeanFactory為設計路線的IOC容器的時候主要有四步:

  • 建立Rerouce資源類,定位到xml。
  • 建立BeanFactory類。
  • 建立Reader類並回撥配置給我們建立的BeanFactory類。
  • 用這個Reader類去載入我們的BeanDefinition

1.1.2 ApplicationContext


可以從類結構圖裡看到Application不僅繼承了我們傳統的BeanFactory設計線路,還繼承了其他介面,這樣使得ApplicationIOC容器的功能更加強大。有以下特點:

  • 支援不同的資訊源
  • 訪問資源,這一特性體現在我們的Resouce和ResourceReader上,這樣我們可以從不同的地方得到BeanDefinition
  • 支援應用事件。這些事件和Bean生命週期的結合為管理Bean提供了便利。

關於Bean的載入和依賴注入其實兩個不同的過程,Bean的載入一般分為三個過程:1.BeanDefinition的定位2.Bean資訊的載入(將具體POJO物件抽象為Bean內部資料結構的過程)3.Bean資訊的註冊(IOC內部會維護一個hashmap去儲存這些Bean資訊)。而我們的依賴注入也就是我們所謂的DI,這裡注意關於IOC和DI你可以將IOC理解成一種設計手段,而DI就是實現這種手段的一種方式 。我們的DI一般發生在我們應用首次呼叫該Bean的時候。當然有一種例外在Bean初始化的時候就發生依賴注入就是我們的懶載入機制。

這裡結束就可以回答開頭的問題,這兩種設計路線的區別,從類結構圖可以看到ApplicationContext已經繼承了Reader類為我們提供了一系列載入不同Resource的讀取器的實現。因此我們程式設計式中就不必為該類IOC容器宣告Reader再進行回撥配置了。

2.1 FileSystemXmlApplicationContext

那麼ApplicationContext類IOC容器在何時配置的讀取器,我們以FileSystemXmlApplicationContext為例:

關於這個讀取器的配置我們可以在它的基類AbstractRefreshableApplicationContext中找到,我們都知道refresh的呼叫是在FileSystemXmlApplicationContext的建構函式中,這是IOC容器初始化的入口。在AbstractRefreshableApplicationContext中有一個抽象方法loadBeanDefinitions(DefaultListableBeanFactory var1),這個抽象方法在 AbstractXmlApplicationContext中有被實現其中就配置了Reader讀取器。

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
        this.initBeanDefinitionReader(beanDefinitionReader);
        this.loadBeanDefinitions(beanDefinitionReader);
    }

相關文章