1. 程式人生 > >Spring IoC容器實現

Spring IoC容器實現

127.0.0.1 兩種 [] 作用 隱式調用 ini 告訴 而是 lee

1,Spring的兩種IoC容器

BeanFactory

  • 基礎類型的IoC容器;
  • 采用延遲初始化策略(容器初始化完成後並不會創建bean的對象,只有當收到初始化請求時才進行初始化);
  • 由於延遲初始化,因此啟動速度較快,占用資源較少;

ApplicationContext

  • 在BeanFactory的基礎上,增加了更為高級的特定:事件發布、國際化等;
  • 在容器啟動時便完成所有bean的創建;
  • 啟動時間較長,占用資源更多;

2,IoC容器的主要類/接口介紹

技術分享圖片

1)BeanFactory
它是一個接口,提供了獲取容器中Bean的相關方法。

2)BeanDefinitionRegistry
它才是IoC的容器,用於存儲、管理所有的Bean對象。

3)DefaultListableBeanFactory
它是IoC容器的一個具體實現,實現了BeanFactory和BeanDefinitionRegistry接口,因此既擁有管理Bean的容器,又擁有訪問Bean的方法。

4)BeanDefinition
每一個Bean都有一個BeanDefinition與之對應,用於存儲Bean的相關信息:對象的class類型、是否是抽象類、構造方法參數等。

RootBeanDefinitionChildBeanDefinition是BeanDefinition的兩個主要的實現類。

5)BeanDefinitionReader

在Spring中,標註Bean的依賴關系有四中方式:

    1. 直接在代碼中聲明
    2. 通過XML文件聲明
    3. 通過Properties文件聲明
    4. 通過註解聲明
      BeanDefinitionReader接口的作用就是讀取配置文件中的bean信息,把它們解析成BeanDefinition對象,然後註冊到BeanDefinitionRegistry中去。
      PropertiesBeanDefinitionReader和XmlBeanDefinitionReader是該接口的兩個實現類,分別用於解析properties和xml格式的配置文件。

6)XmlBeanFactory
它是一個集成了XmlBeanDefinitionReader功能的BeanFactory,用於簡化初始化操作。

3,BeanFactory的兩個重要階段

容器啟動階段

該階段Spring會使用BeanDefinitionReader加載配置文件,並把所有的bean解析成BeanDefinition對象,並註冊到BeanDefinitionRegistry

Bean實例化階段

對於BeanFactory容器,當調用者主動調用getBean方法或者因存在依賴關系容器隱式調用getBean時,如果當前Bean尚未初始化,或者bean配置成prototype,就會觸發Bean實例的初始化

4,BeanFactoryPostProcessor:一種容器擴展機制

Spring提供了BeanFactoryPostProcessor這種容器擴展機制,它允許我們在容器啟動完成後Bean實例化前插入額外的操作

BeanFactoryPostProcessor提供了三個實現類:

1.PropertyPlaceholderConfigurer
  一般情況下,我們並不會將數據庫連接信息直接寫死在dataSource這個bean中,而是將它們單獨寫在一個properties文件中,這樣易於修改與閱讀。而bean中使用占位符代替這些屬性值,當容器啟動完成後,在Bean初始化前用properties文件中的值替換占位符,再創建對象。
PropertyPlaceholderConfigurer就能實現這樣的功能。

  • xml中作如下配置:
<bean id="dataSource" class="xxxxxx">
    <property name="url">
        <value>${jdbc.url}</value>
    </property>
    <property name="username">
        <value>${jdbc.username}</value>
    </property>
</bean>
  • 使用properties文件存儲屬性值:
jdbc.url=jdbc:mysql://127.0.0.1:3306
jdbc.username=root

當容器啟動完成後dataSource的BeanDefinition對象將會被註冊進BeanDefinitionRegistry中,此時BeanDefinition中的屬性值仍然是占位符的形式;接下倆,PropertyPlaceholderConfigurer就會發揮作用,它會將占位符用properties文件中的屬性值替換掉。接下來bean就可以被正確地創建。

2.PropertyOverrideConfigurer
它的功能與PropertyPlaceholderConfigurer類似,也需要指定一個properties文件,只不過它會用配置文件中設置的那些bean的屬性值替換指定bean的屬性值。

  • xml中作如下配置:
<bean id="dataSource" class="xxxxxx">
    <property name="url">
        <value>jdbc:mysql://127.0.0.1:3306</value>
    </property>
    <property name="username">
        <value>chai</value>
    </property>
</bean>
  • 使用properties文件存儲屬性值:
dataSource.url=jsbc:mysql://127.0.0.1:3307
dataSource.username=root

PropertyOverrideConfigurer會在容器啟動完畢後、Bean對象創建之前,通過修改BeanDefinition對象,替換指定的屬性值。
properties文件的內容必須遵循如下格式:

bean的名字.屬性名=屬性值

3.CustomEditorConfigurer

該類用於向Spring容器增添自定義的PropertyEditor對象。

  容器啟動結束後bean創建之前,配置文件中所有的bean都被解析成BeanDefinition對象,該對象中關於bean所有的信息都是String類型的,若要創建bean對象,就需要將這些String類型的信息解析成它們原本的類型。在Spring中,每種類型都有對應一個PropertyEditor類,該類中封裝了String與該類型的轉換方法。當然,對於某些類型Spring並未提供相應的PropertyEditor時,我們可以自定義PropertyEditor,並使用CustomEditorConfigurer將其告訴Spring容器,讓它在遇到該類型的時候采用我們自定義的PropertyEditor去解析。

Spring提供的部分PropertyEditor:

    • StringArrayPropertyEditor
      將字符串轉換成String[],默認以,分割。
    • ClassEditor
      類似於Class.forname(String),將字符串轉換成class對象。
    • FileEditor
      將字符串轉換成File對象。
    • URLEditor
      將字符串轉換成URL對象。
    • InputStreamEditor
      將字符串轉換成InputStream對象。
    • LocaleEditor
      將字符串轉換成Locale對象。
    • PatternEditor
      將字符串轉換成Pattern對象。

以上類型的字符串,Spring會自動將它們轉換成原本的類型。而我們自定義的PropertyEditor必須要通過CustomEditorConfigurer將其加入容器。

如何開啟BeanFactoryPostProcessor功能?
1.BeanFactory

// 創建BeanFactory對象
ConfigurableListableBeanFactory beanFactory = new XmlBeanFactory( new ClassPathResource("xxx") );
// 創建BeanFactoryPostProcessor對象
PropertyPlaceholderConfigurer processor = new PropertyPlaceholderConfigurer();
// 設置properties文件的位置
processor.setLocation("xxx");
// 將其傳遞給beanFactory
processor.postProcessBeanFactory(beanFactory);

2.ApplicationContext
ApplicationContext會自動檢測配置文件中出現的BeanFactoryPostProcessor,因此只需要在配置文件中聲明所使用的BeanFactoryPostProcessor即可。

<bean class="xxxxx.PropertyPlaceholderConfigurer">
    <property>
        <list>
            <value>properties文件路徑</value>
        </list>
    </property>
</bean>

https://blog.csdn.net/u010425776/article/details/55269888

Spring IoC容器實現