1. 程式人生 > >spring學習-ApplicationContext-spring上下文深入理解

spring學習-ApplicationContext-spring上下文深入理解

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:

複製程式碼

複製程式碼

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);

複製程式碼

複製程式碼

   但是如果應用裡面有多個屬性配置檔案,則應該採用BeanFactory的子介面ApplicationContext來建立BeanFactory的例項。ApplicationContext通常使用如下兩個實現類:

          FileSystemXmlApplicationContext:以基於檔案系統的XML配置檔案建立ApplicationContext例項。

          ClassPathXmlApplicationContext:以類載入路徑下的XML配置檔案建立的ApplicationContext例項。

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

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"});

           二、讓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容器作為引數傳入該方法。

複製程式碼

複製程式碼

 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 }

複製程式碼

複製程式碼

        上面的Chinese類實現了ApplicationContext介面,並實現了該介面提供的setApplicationContextAware()方法,這就使得該Bean例項可以直接訪問到建立她的Spring容器。

         將該Bean部署在Spring容器中。

         測試類:

         該程式先通過例項化的方法來獲取ApplicationContext,然後通過chinese Bean來獲得BeanFactory,並將兩者進行比較。

複製程式碼

複製程式碼

 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 }

複製程式碼

複製程式碼

       結果如下:

         true

         上面的程式碼雖然實現了ApplicationContextAware介面讓Bean擁有了訪問容器的能力,但是汙染了程式碼,導致程式碼與Spring介面耦合在一起。所以,如果不是特別需要,一般不建議直接訪問容器。