Spring Framework 官方文檔——核心技術


未完結,請稍后再看

版本:5.1.11.BUILD-SNAPSHOT

參考文檔的這一部分涵蓋了Spring框架的所有不可或缺的技術。

Spring框架中最重要的就是控制反轉(IoC)容器。介紹完IoC容器以后,接下來將全面介紹Spring的面向切面編程(AOP)技術。Spring框架有自己的AOP框架,該框架概念簡單,並且八成的企業級AOP需求都能滿足。

Spring框架還提供了與AspectJ框架的集成。AspectJ的功能是目前最豐富的——當然,它也是Java企業領域最成熟的AOP實現。

IoC容器

本章介紹了Spring的控制反轉(IoC)容器。

Ioc容器和Bean簡介

本章介紹了Spring框架對控制反轉(IoC)思想的實現。IoC亦稱作依賴注入(DI)。在控制反轉的過程中,對象僅通過構造函數參數、工廠方法參數或者對象實例上設置的屬性來定義其依賴項。[譯者注:有點繞呵,看不懂先接着往下看一看吧~] 然后,容器在創建Bean時注入哪些依賴項。這個過程與Bean自己控制依賴的實例化和定位的過程相反,因此稱之為控制反轉。

org.springframework.beans org.springframework.context 包是Spring框架中IoC容器的基礎。BeanFactory接口提供了高級的配置機制來管理任意類型的對象。ApplicationContextBeanFactory的子接口,它做了如下增強:

  • 與Spring的AOP特性集成更容易。
  • 消息資源處理(用於國際化)。
  • 特定的應用層上下文,例如:WebApplicationContext用於WEB應用。

簡而言之,BeanFactory提供了配置框架和基礎功能,ApplicationContext則增加了更多的企業級功能。ApplicationContextBeanFactory的完超集,在本章中描述的Spring的IoC容器都是指它。有關使用BeanFactory而不是ApplicationContext的信息,請參見有關BeanFactory的章節。

在Spring中,構成應用程序主干並且由Spring IoC容器管理的對象稱為Bean。Bean是由Spring IoC容器實例化、組裝和管理的對象。除此以外,Bean僅僅是應用程序中眾多對象之一,Bean及其之間的依賴關系反隱在容器使用的配置元數據中。

容器概覽

org.springframework.context.ApplicationContext接口代表了Spring的IoC容器,它負責實例化、配置和組裝Bean。容器通過讀取配置元數據來獲取將要實例化、配置、組裝的對象的說明。配置元數據的表現形式有XML、Java注解或Java代碼。通過他們,你可以表達出哪些組成你的應用程序的對象以及他們之間豐富的依賴關系。

Spring內置了幾種ApplicationContext的實現。在獨立的應用程序中,通常創建ClassPathXmlApplicationContext或者FileSystemXmlApplicationContext。XML是傳統的配置元數據定義格式,你還可以通過提供少量的XML配置來聲明棄用對其他元數據格式的支持,然后指示容器將Java注釋或者代碼作為元數據格式。

在大多數應用場景中,不需要顯式的用戶代碼即可實例化一個或多個Spring IoC容器。例如,在Web應用場景中,只需要web.xml中的八行樣板代碼就夠了。如果使用 Spring Tool Suite(基於Eclipse的開發環境),則只需單擊幾次鼠標或按幾次鍵盤即可輕松創建此樣板配置。

下圖顯示了Spring的工作原理的高級視圖。由於你的應用程序類與配置元數據結合在一起,因此,在ApplicationContext創建和初始化以后你將擁有一個完全配置且可執行的系統或應用程序。

配置元數據

如上圖所示,Spring IoC容器使用配置元數據的形式(來描述容器)。這個配置元數據表示你作為應用程序開發者,告訴Spring容器該如何實例化、配置以及組裝對象。

XML是提供配置元數據的典型形式,本章我們將使用這種形式來闡述Spring IoC容器的關鍵概念和特性。

配置元數據並不限於XML形式。Spring IoC容器和配置元數據的格式之間是松耦合的。現下,更多的開發者選擇使用基於Java代碼的配置形式。

有關在Spring容器中使用其他形式的配置元數據的信息,請參見:

  • 基於注釋的配置:Spring 2.5引入了對基於注釋的配置元數據的支持。
  • 基於Java的配置:從Spring 3.0開始,Spring JavaConfig項目提供的許多功能成為核心Spring框架的一部分。因此,您可以使用Java而不是XML文件來定義應用程序類外部的bean。要使用這些新功能,請參閱 @Configuration@Bean@Import,和@DependsOn注釋。

譯者注:上述的幾個URL連接的是英文的文檔,請知悉。我認為跳躍式地看文檔並不是一個好的習慣,后續章節中,有些原文檔中存在的連接可能會被取消,望知悉。后不再贅述。

Spring應用中至少包含一個由容器管理的Bean。使用XML配置時,通常在頂<beans/> 節點內插入<bean/> 節點,<bean/> 節點對應了程序中的Bean。基於Java的配置通常在由@Configuration 標記的類中使用@Bean注解來標記方法,被標記的方法的返回值就是Bean。

Bean定義和組成應用程序的對象一一對應。通常,你會定義服務層對象、數據訪問層對象(DAO)、表現層對象(例如Struts的實例)、基礎設施對象(例如HibernateSessionFactories,JMS Queues等 )。我們通常不會在容器中配置實體對象,因為這是DAO層和業務邏輯的職責。不過,你可以通過將Spring與Aspec集成起來,來配置一些在IoC容器外部創建的對象。詳情請參見:通過AspectJ在Spring中注入實體對象。

下面的例子展示了XML形式的配置元數據的基本結構:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="..." class="..."> ① ②
        <!-- collaborators and configuration for this bean go here -->
    </bean>
    
    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>
    
    <!-- more bean definitions go here -->
    
</beans>

id屬性是標識Bean定義的字符串。

class屬性定義了Bean的類型,它的值是類的全限定名。

id屬性的值可以被協作對象引用。本例中沒有展示協作Bean引用依賴Bea更多信息請看依賴注入章節。

實例化容器

ApplicationContext類的構造函數的路徑參數是配置元數據的資源文件路徑,容器根據這些資源路徑去加載各種外部資源,這些 資源路徑可能是本地文件系統路徑、Java類路徑等。

ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

在了解了Spring的IoC容器以后,你可能會想了解更多有關Spring中資源的抽象。資源提供了一種方便的機制來從采用URI語法定義的位置讀取輸入流。具體而言,資源路徑用來描述應用程序上下文(正如應用程序上下文和資源路徑章節中描述的那樣)。

下面的例子展示了服務層對象的配置文件(services.xml):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- services -->

    <bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
        <property name="accountDao" ref="accountDao"/>
        <property name="itemDao" ref="itemDao"/>
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions for services go here -->

</beans>

下面的例子展示了數據存儲層對象的配置文件(daos.xml):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="accountDao"
        class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions for data access objects go here -->

</beans>

在上面的例子中,服務層由PetStoreServiceImpl 類和兩個數據存取層對象(分別為JpaAccountDaoJpaItemDao類對象)組成。property元素的name屬性是指JavaBean屬性的名稱,ref屬性則是另一個Bean定義的ididref之間的聯系,表達了協作對象之間的依賴關系。有關對象依賴注入的配置的更多信息,請參見依賴注入章節。

組織基於XML的配置元數據

將Bean定義分散在多個XML文件中可能會很有用。通常,每個單獨的XML配置文件都代表體系結構中的邏輯層或模塊。

你可以使用應用程序上下文的構造器來從這些XML片段中加載Bean定義,正如前一章節看到的那樣,應用程序上下文容器的構造函數可以加載多個資源路徑。或者,我們可以使用<import/> 元素去加載另一個文件中的Bean定義。下面的例子展示了操作方法:

<beans>
    <import resource="services.xml"/>
    <import resource="resources/messageSource.xml"/>
    <import resource="/resources/themeSource.xml"/>

    <bean id="bean1" class="..."/>
    <bean id="bean2" class="..."/>
</beans>

在前面的例子中,外部Bean定義是從 services.xmlmessageSource.xmlthemeSource.xml 三個配置文件中加載。所有的位置路徑都是相對於做導入操作的文件的位置路徑,因此services.xml必須在同級目錄,messageSource.xmlthemeSource.xml必須在resources目錄下(resources目錄和做導入操作的文件在同一層)。我們可以看到,反斜杠在這里被忽略了。但是,鑒於 這里都是使用相對路徑,我們最好還是不要使用反斜杠。根據<beans/>的文件約束,導入的文件的內容必須是有效的XML Bean定義。

可以使用"../"路徑來引用父目錄中的文件,但是不建議這樣做。如果引用了父目錄,可能會造成對當前應用程序外部的文件進行依賴。特別是在classpath:URL(例如:classpath:../services.xml)這種形式下不推薦使用。這種形式在運行時選擇最近的類路徑根目錄,然后再去尋找其父目錄,在淚目鏡配置更改以后,可能會導致選擇了其他的錯誤目錄。

你可以使用資源的全限定路徑來代替相對路徑:例如file:C:/config/services.xmlclasspath:/config/services.xml。但是,請注意你正在將應用程序耦合到特定的絕對位置。通常最好為這樣的絕對位置保留一個間接尋址,例如,通過在運行時針對JVM系統屬性解析的“ $ {…}”占位符。

命名空間本身提供了import指令功能。Spring提供的一系列XML名稱空間(例如contextutil名稱空間)中提供了超出普通bean定義的其他配置功能。

Groovy:Bean定義領域特定語言

現在舉另一個外部化的配置元數據的例子:使用領域特定語言Groovy語言來表達Bean定義。Groovy語言因為Grails框架而聞名於世。通常,這些配置位於".groovy"文件中,結構如下例所示:

beans {
    dataSource(BasicDataSource) {
        driverClassName = "org.hsqldb.jdbcDriver"
        url = "jdbc:hsqldb:mem:grailsDB"
        username = "sa"
        password = ""
        settings = [mynew:"setting"]
    }
    sessionFactory(SessionFactory) {
        dataSource = dataSource
    }
    myService(MyService) {
        nestedBean = { AnotherBean bean ->
            dataSource = dataSource
        }
    }
}

這種配置樣式在很大程度上等同於XML bean定義,甚至支持Spring的XML配置的命名空間。它還允許通過importBeans指令導入XML bean定義文件。

使用容器

ApplicationContext是維護Bean定義以及Bean依賴關系注冊表的高級工廠的接口。通過使用方法T getBean(String name, Class<T> requiredType),你可以檢索bean的實例。

下例展示了使用ApplicationContext來讀取Bean定義:

// create and configure beans
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

// retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class);

// use configured instance
List<String> userList = service.getUsernameList();

使用Groovy的配置,它的引導方法看起來非常相似。他有一個不同的上下文實現類,該類可識別Groovy(但也了解XML形式的Bean定義)。以下示例顯示了如何引導Groovy配置:

ApplicationContext context = new GenericGroovyApplicationContext("services.groovy", "daos.groovy");

最靈活的變體是GenericApplicationContext 與讀取器委托結合使用——例如與XmlBeanDefinitionReader 結合來讀取XML文件:

GenericApplicationContext context = new GenericApplicationContext();
new XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml");
context.refresh();

你也可以使用``GroovyBeanDefinitionReader  來讀取Groovy文件:

GenericApplicationContext context = new GenericApplicationContext();
new GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy");
context.refresh();

你可以在同一個ApplicationContext里面混用這些閱讀器,這樣你就可以把Bean定義配置在不同形式的資源中。

你可以使用getBean來檢索Bean實例。ApplicationContext接口還有幾種其他的方式來檢索Bean,但是理想情況下,你永遠也不要在代碼里使用。事實上,你的應用程序代碼根本不應該調用getBean方法,這樣應用程序才完全不依賴Spring的API。例如,Spring與Web框架的集成為各種Web框架組件(例如控制器和JSF管理的Bean)提供了依賴項注入,使你可以通過元數據(例如自動裝配注解)聲明對特定Bean的依賴。

Bean概覽


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM