天天看點

Spring 讀書筆記——Spring容器

作者:Java小玖

Spring有兩個核心接口:BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口。他們都可代表Spring容器,Spring容器是生成Bean執行個體的工廠,并且管理容器中的Bean。

Bean是Spring管理的基本機關,在基于Spring的Java EE應用中,所有的元件都被當成Bean處理,包括資料源、Hibernate的SessionFactory、事務管理器等。在Spring中,Bean的是一個非常廣義的概念,任何的Java對象、Java元件都被當成Bean處理。

而且應用中的所有元件,都處于Spring的管理下,都被Spring以Bean的方式管理,Spring負責建立Bean執行個體,并管理他們的生命周期。Bean在Spring容器中運作,無須感受Spring容器的存在,一樣可以接受Spring的依賴注入,包括Bean屬性的注入,協作者的注入、依賴關系的注入等。

Spring容器負責建立Bean執行個體,是以需要知道每個Bean的實作類,Java程式面向接口程式設計,無須關心Bean執行個體的實作類;但是Spring容器必須能夠精确知道每個Bean執行個體的實作類,是以Spring配置檔案必須精确配置Bean執行個體的實作類。

一、Spring容器

Spring容器最基本的接口就是BeanFactor。BeanFactory負責配置、建立、管理Bean,他有一個子接口:ApplicationContext,是以也稱之為Spring上下文。Spring容器負責管理Bean與Bean之間的依賴關系。

BeanFactory接口包含以下幾個基本方法:

Ø Boolean containBean(String name):判斷Spring容器是否包含id為name的Bean執行個體。

Ø <T> getBean(Class<T> requiredTypr):擷取Spring容器中屬于requiredType類型的唯一的Bean執行個體。

Ø Object getBean(String name):傳回Sprin容器中id為name的Bean執行個體。

Ø <T> T getBean(String name,Class requiredType):傳回容器中id為name,并且類型為requiredType的Bean

Ø Class <?> getType(String name):傳回容器中指定Bean執行個體的類型。

調用者隻需使用getBean()方法即可獲得指定Bean的引用,無須關心Bean的執行個體化過程。即Bean執行個體的建立過程完全透明。

在使用BeanFactory接口時,我們一般都是使用這個實作類:org.springframework.beans.factory.xml.XmlBeanFactory。然而ApplicationContext作為BeanFactory的子接口,使用它作為Spring容器會更加友善。它的實作類有:FileSystemXmlApplicationContext、ClassPathXmlApplicationContext、AnnotationConfigApplicationContext。

建立Spring容器執行個體時,必須提供Spring容器管理的Bean的詳細配置資訊。Spring的配置資訊通常采用xml配置檔案來設定,是以,建立BeanFactory執行個體時,應該提供XML配置檔案作為參數。

XML配置檔案通常使用Resource對象傳入。Resource接口是Spring提供的資源通路接口,通過使用該接口,Spring能夠以簡單、透明的方式通路磁盤、類路徑以及網絡上的資源。

對于Java EE應用而言,可在啟動Web應用時自動加載ApplicationContext執行個體,接受Spring管理的Bean無須知道ApplicationContext的存在。一般使用如下方式執行個體化BeanFactory:

Spring 讀書筆記——Spring容器
1                 //搜尋目前檔案路徑下的bean.xml檔案建立Resource對象
2         InputStreamSource isr = new FileSystemResource("bean.xml");
3         //以Resource對象作為參數建立BeanFactory執行個體
4         XmlBeanFactory factory = new XmlBeanFactory((Resource) isr);
5 或
6         ClassPathResource res = new ClassPathResource("bean.xml");
7         //以Resource對象作為參數建立BeanFactory執行個體
8         XmlBeanFactory factory = new XmlBeanFactory(res);           
Spring 讀書筆記——Spring容器
但是如果應用裡面有多個屬性配置檔案,則應該采用BeanFactory的子接口ApplicationContext來建立BeanFactory的執行個體。ApplicationContext通常使用如下兩個實作類:           

FileSystemXmlApplicationContext:以基于檔案系統的XML配置檔案建立ApplicationContext執行個體。

ClassPathXmlApplicationContext:以類加載路徑下的XML配置檔案建立的ApplicationContext執行個體。

如果需要同時加載多個XML配置檔案,采用如下方式:

Spring 讀書筆記——Spring容器
1         //搜尋CLASSPATH路徑,以classpath路徑下的bean.xml、service.xml檔案建立applicationContext
2         ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"bean.xml","service.xml"});
3         
4         //以指定路徑下的bean.xml、service.xml檔案建立applicationContext
5         ApplicationContext ctx1 = new FileSystemXmlApplicationContext(new String[]{"bean.xml","service.xml"});           
Spring 讀書筆記——Spring容器

二、讓Bean擷取Spring容器

在前面簡單的介紹了Spring容器。在Spring中我們可以使用Spring容器中getBean()方法來擷取Spring容器中的Bean執行個體。在這樣的通路模式下,程式中總是持有Spring容器的引用。但是在實際的應用中,Spring容器通常是采用聲明式方式配置産生:記開發者隻要在web.xml檔案中配置一個Listener,該Listener将會負責初始化Spring容器。在這種情況下,容器中Bean處于容器管理下,無須主動通路容器,隻需要接受容器的注入管理即可。同時Bean執行個體的依賴關系通常也是由容器冬天注入,無須Bean執行個體主動請求。

在這種情況下,Sprig容器中Bean通常不會需要通路容器中其他的Bean—采用依賴注入,讓Spring把被依賴的Bean注入到依賴的Bean中即可。

實作BeanFactoryAware接口的Bean,擁有通路的BeanFactory容器的能力,實作BeanFactoryAware接口的Bean執行個體将會擁有對容器的通路能力。BeanFactoryAware接口僅有如下一個方法:

SetBeanFactory(BeanFactory beanFactory):該方法有一個參數beanFactory,該參數指向建立它的BeanFactory。

該方法将由Spring調動,當Spring調用該方法時會将Spring容器作為參數傳入該方法。

Spring 讀書筆記——Spring容器
1 public class Chinese implements ApplicationContextAware{
 2 
 3     //将BeanFactory容器以成員變量儲存
 4     private ApplicationContext ctx;
 5     /**
 6      * 實作ApplicationContextAware接口實作的方法
 7      */
 8     public void setApplicationContext(ApplicationContext cyx)
 9             throws BeansException {
10         this.ctx = ctx;
11     }
12     
13     //擷取ApplicationContext的測試方法
14     public ApplicationContext getContext(){
15         return ctx;
16     }
17 
18 }           
Spring 讀書筆記——Spring容器

上面的Chinese類實作了ApplicationContext接口,并實作了該接口提供的setApplicationContextAware()方法,這就使得該Bean執行個體可以直接通路到建立她的Spring容器。

将該Bean部署在Spring容器中。

測試類:

該程式先通過執行個體化的方法來擷取ApplicationContext,然後通過chinese Bean來獲得BeanFactory,并将兩者進行比較。

Spring 讀書筆記——Spring容器
1 public class ChineseTest {
 2 
 3     public static void main(String[] args) {
 4         ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
 5         Chinese c = ctx.getBean("chinese",Chinese.class);
 6         System.out.println(c.getContext());
 7         
 8         System.out.println(c.getContext()==ctx);
 9         
10     }
11 }           
Spring 讀書筆記——Spring容器

結果如下:

true

上面的代碼雖然實作了ApplicationContextAware接口讓Bean擁有了通路容器的能力,但是污染了代碼,導緻代碼與Spring接口耦合在一起。是以,如果不是特别需要,一般不建議直接通路容器。

Spring 讀書筆記——Spring容器

繼續閱讀