更新於三月三十一號 21:01html
This part of the reference documentation covers all the technologies that are absolutely integral to the Spring Framework.java
Foremost amongst these is the Spring Framework’s Inversion of Control (IoC) container. A thorough treatment of the Spring Framework’s IoC container is closely followed by comprehensive coverage of Spring’s Aspect-Oriented Programming (AOP) technologies. The Spring Framework has its own AOP framework, which is conceptually easy to understand and which successfully addresses the 80% sweet spot of AOP requirements in Java enterprise programming.ios
Coverage of Spring’s integration with AspectJ (currently the richest — in terms of features - and certainly most mature AOP implementation in the Java enterprise space) is also provided.程序員
This chapter covers Spring’s Inversion of Control (IoC) container.web
This chapter covers the Spring Framework implementation of the Inversion of Control (IoC) principle. IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern.spring
The org.springframework.beans and org.springframework.context packages are the basis for Spring Framework’s IoC container. The BeanFactory interface provides an advanced configuration mechanism capable of managing any type of object. ApplicationContext is a sub-interface of BeanFactory. It adds:express
In short, the BeanFactory provides the configuration framework and basic functionality, and the ApplicationContext adds more enterprise-specific functionality. The ApplicationContext is a complete superset of the BeanFactory and is used exclusively in this chapter in descriptions of Spring’s IoC container. For more information on using the BeanFactory instead of the ApplicationContext, see The BeanFactory.bash
In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container.架構
The org.springframework.context.ApplicationContext
interface represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans. The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata. The configuration metadata is represented in XML, Java annotations, or Java code. It lets you express the objects that compose your application and the rich interdependencies between those objects.app
Several implementations of the ApplicationContext
interface are supplied with Spring. In stand-alone applications, it is common to create an instance of ClassPathXmlApplicationContext
or FileSystemXmlApplicationContext
. While XML has been the traditional format for defining configuration metadata, you can instruct the container to use Java annotations or code as the metadata format by providing a small amount of XML configuration to declaratively enable support for these additional metadata formats.
In most application scenarios, explicit user code is not required to instantiate one or more instances of a Spring IoC container. For example, in a web application scenario, a simple eight (or so) lines of boilerplate web descriptor XML in the web.xml file of the application typically suffices (see Convenient ApplicationContext Instantiation for Web Applications). If you use the Spring Tool Suite (an Eclipse-powered development environment), you can easily create this boilerplate configuration with a few mouse clicks or keystrokes.
The following diagram shows a high-level view of how Spring works. Your application classes are combined with configuration metadata so that, after the ApplicationContext is created and initialized, you have a fully configured and executable system or application.
As the preceding diagram shows, the Spring IoC container consumes a form of configuration metadata. This configuration metadata represents how you, as an application developer, tell the Spring container to instantiate, configure, and assemble the objects in your application.
Configuration metadata is traditionally supplied in a simple and intuitive XML format, which is what most of this chapter uses to convey key concepts and features of the Spring IoC container.
XML-based metadata is not the only allowed form of configuration metadata. The Spring IoC container itself is totally decoupled from the format in which this configuration metadata is actually written. These days, many developers choose Java-based configuration for their Spring applications.
For information about using other forms of metadata with the Spring container, see:
Spring configuration consists of at least one and typically more than one bean definition that the container must manage. XML-based configuration metadata configures these beans as <bean/>
elements inside a top-level <beans/>
element. Java configuration typically uses @Bean-annotated methods within a @Configuration
class.
These bean definitions correspond to the actual objects that make up your application. Typically, you define service layer objects, data access objects (DAOs), presentation objects such as Struts Action instances, infrastructure objects such as Hibernate SessionFactories, JMS Queues, and so forth. Typically, one does not configure fine-grained domain objects in the container, because it is usually the responsibility of DAOs and business logic to create and load domain objects. However, you can use Spring’s integration with AspectJ to configure objects that have been created outside the control of an IoC container. See Using AspectJ to dependency-inject domain objects with Spring.
The following example shows the basic structure of XML-based configuration metadata:
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="..." class="..."> (1)(2)
<!-- 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>
(1) The id attribute is a string that identifies the individual bean definition.
(2) The class attribute defines the type of the bean and uses the fully qualified classname.
複製代碼
The value of the id attribute refers to collaborating objects. The XML for referring to collaborating objects is not shown in this example. See Dependencies for more information.
The location path or paths supplied to an ApplicationContext
constructor are resource strings that let the container load configuration metadata from a variety of external resources, such as the local file system, the Java CLASSPATH
, and so on.
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
複製代碼
After you learn about Spring’s IoC container, you may want to know more about Spring’s Resource abstraction (as described in Resources), which provides a convenient mechanism for reading an InputStream from locations defined in a URI syntax. In particular, Resource paths are used to construct applications contexts, as described in Application Contexts and Resource Paths.
The following example shows the service layer objects (services.xml) configuration file:
<?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 http://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>
複製代碼
The following example shows the data access objects daos.xml
file:
<?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 http://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>
複製代碼
In the preceding example, the service layer consists of the PetStoreServiceImpl class and two data access objects of the types JpaAccountDao and JpaItemDao (based on the JPA Object-Relational Mapping standard). The property name element refers to the name of the JavaBean property, and the ref element refers to the name of another bean definition. This linkage between id and ref elements expresses the dependency between collaborating objects. For details of configuring an object’s dependencies, see Dependencies.
Composing XML-based Configuration Metadata
It can be useful to have bean definitions span multiple XML files. Often, each individual XML configuration file represents a logical layer or module in your architecture.
You can use the application context constructor to load bean definitions from all these XML fragments. This constructor takes multiple Resource
locations, as was shown in the previous section. Alternatively, use one or more occurrences of the <import/>
element to load bean definitions from another file or files. The following example shows how to do so:
<beans>
<import resource="services.xml"/>
<import resource="resources/messageSource.xml"/>
<import resource="/resources/themeSource.xml"/>
<bean id="bean1" class="..."/>
<bean id="bean2" class="..."/>
</beans>
複製代碼
In the preceding example, external bean definitions are loaded from three files: services.xml
, messageSource.xml
, and themeSource.xml
. All location paths are relative to the definition file doing the importing, so services.xml
must be in the same directory or classpath location as the file doing the importing, while messageSource.xml
and themeSource.xml
must be in a resources
location below the location of the importing file. As you can see, a leading slash is ignored. However, given that these paths are relative, it is better form not to use the slash at all. The contents of the files being imported, including the top level <beans/>
element, must be valid XML bean definitions, according to the Spring Schema.
It is possible, but not recommended, to reference files in parent directories using a relative "../" path. Doing so creates a dependency on a file that is outside the current application. In particular, this reference is not recommended for
classpath:
URLs (for example,classpath:../services.xml
), where the runtime resolution process chooses the 「nearest」 classpath root and then looks into its parent directory. Classpath configuration changes may lead to the choice of a different, incorrect directory. You can always use fully qualified resource locations instead of relative paths: for example,file:C:/config/services.xml
or classpath:/config/services.xml
. However, be aware that you are coupling your application’s configuration to specific absolute locations. It is generally preferable to keep an indirection for such absolute locations — for example, through "${…}" placeholders that are resolved against JVM system properties at runtime.
The namespace itself provices the import directive feature. Further configuration features beyond plain bean definitions are available in a selection of XML namespaces provided by Spring — for example, the context and util namespaces.
The ApplicationContext
is the interface for an advanced factory capable of maintaining a registry of different beans and their dependencies. By using the method T getBean(String name, Class<T> requiredType)
, you can retrieve instances of your beans.
The ApplicationContext
lets you read bean definitions and access them, as the following example shows:
// 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();
複製代碼
The most flexible variant is GenericApplicationContext
in combination with reader delegates — for example, with XmlBeanDefinitionReader
for XML files, as the following example shows:
GenericApplicationContext context = new GenericApplicationContext();
new XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml");
context.refresh();
複製代碼
You can mix and match such reader delegates on the same ApplicationContext, reading bean definitions from diverse configuration sources.
You can then use getBean to retrieve instances of your beans. The ApplicationContext interface has a few other methods for retrieving beans, but, ideally, your application code should never use them. Indeed, your application code should have no calls to the getBean() method at all and thus have no dependency on Spring APIs at all. For example, Spring’s integration with web frameworks provides dependency injection for various web framework components such as controllers and JSF-managed beans, letting you declare a dependency on a specific bean through metadata (such as an autowiring annotation).
這部分參考文檔涵蓋絕大部分 Spring 框架使用的技術。
最重要的是 Spring 框架的 IoC 容器,與它關係密切的是 Spring AOP 技術。Spring 有它本身易於理解的 AOP 框架,併成功解決了 80% 在 Java 企業開發中對 AOP 的要求。
Spring 也能集成 AspectJ(當前擁有最多特性,在 Java 企業開發領域最成熟的 AOP 實現)。
這一章講述 Spring IoC 容器。
這一章包含 Spring 框架實現控制反轉(IoC)的原理。IoC 也被稱爲依賴注入(Dependency Injection)。經過對象定義它的依賴,僅能經過構造器參數、工廠方法的參數,在那些在對象初始化以後的屬性或者工廠方法返回結果。容器在建立 Bean 時,再將它依賴的 Bean 注入。這個過程與 Bean 控制依賴屬性的實例化,或經過類構造器或如像 Service Locator 這樣的機制相比是徹底相反的(所以叫作控制反轉)。
org.springframework.beans
和 org.springframework.context
包是 Spring IoC 容器的基礎。BeanFactory
接口提供了一個管理任何類型對象的機制。ApplicationContext
是 BeanFactory
的子接口,它添加了以下特性:
WebApplicationContext
簡而言之,BeanFactory
提供了配置和基本功能,ApplicationContext
則添加了更多企業開發的功能。ApplicationContext
是 BeanFactory
的超集,它僅僅在本章 Spring IoC 容器中有描述。
在 Spring 框架中,應用中建立並被 Spring IoC 容器管理的對象稱爲「Bean」。Bean 的初始化、裝配等被 Spring IoC 容器管理。Beans 以及他們的依賴項,映射爲配置元數據被 Spring 使用。
ApplicationContext
接口表明 Spring IoC 容器,負責 Bean 的實例化、配置以及組裝工做。Spring 容器經過讀取配置元信息來獲取對象實例化、配置以及組裝的說明。配置元信息以 XML、註解或者配置類的形式存在。配置元信息用來表述那些構成你應用的對象,以及對象之間的相互依賴關係。
Spring 提供了 ApplicationContext
接口的一些實現。在應用中,常常建立 ClassPathXmlApplicationContext
或者 FileSystemXmlApplicationContext
。雖然 XML 是定義配置元數據的傳統方式,你仍舊能夠用 Java 註解或者代碼來指示容器,只須要在 XML 配置中聲明支持這些額外數據源格式。
在大多數狀況下,不須要爲容器中的 Bean 對象做出明確編碼。好比在 Web 應用的 web.xml 中,大概八行樣板代碼就足夠了。你也可使用 Spring Tool Suite,經過鼠標單擊和鍵盤操做來建立樣板配置。
下圖粗略的展現了 Spring 是如何工做的。你的應用類和配置元信息綁定在一塊兒,所以在 ApplicationContext
建立和初始化後,你會獲得一個徹底配置好的且能執行的應用。
如上圖所示,Spring IoC 容器消費着由配置元數據組成的表格。配置元數據表明着你做爲應用開發者,告知 Spring 容器來初始化、配置以及組裝應用中的對象。
傳統上,配置元數據以簡單直觀的 XML 格式提供。本章大部份內容用於傳達 Spring IoC 容器的核心概念和特性。
XML 格式不是配置元信息的惟一格式,Spring IoC 容器與元信息的配置格式徹底解耦。最近不少程序員選擇基於 Java 的配置格式。
使用 Spring 容器的其餘元信息格式,如:
@Configuration
、@Bean
、@Import
以及 @DependsOn
註解來應用這些特性。Spring 配置文件包含至少一個(一般是多個)Bean 定義。基於 XML 的配置元文件,在外層 <beans/>
標籤內的 <bean/>
標籤中定義單個 Bean。Java 配置一般在 @Configuration
標記的類中,定義 @Bean
註解的方法。
這些 Bean 定義對應着您應用中的實際對象。一般狀況,您會定義服務層對象(Service)、數據訪問對象(data access objects)、展現層(如 Struts)實例、基礎設施對象(如 Hibernate SessionFactories, JMS Queues 等)。一般不須要在容器中建立細粒度的領域對象,由於這由 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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="..." class="..."> (1)(2)
<!-- 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>
(1) String 類型的 id 屬性,是定義 bean 的標識
(2) class 屬性使用全類名定義 bean 的類型
複製代碼
屬性 id
關聯着相應的對象。實例中給出的並不完整,在 Dependencies 章節查看詳細內容。
在 ApplicationContext
構造器中提供的本地路徑或者多個路徑(如本地文件系統,Java CLASSPATH),指導容器從外部配置中加載配置元信息。
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
複製代碼
在你學習 Spring IoC 容器後,你可能想深刻了解 Spring 抽象的
Resource
,它提供了方便的機制從 URI 格式定義的 InputStream 流中讀取信息。尤爲是,Resource
路徑被用來構造應用上下文,在 Application Contexts and Resource Paths 中有描述。
下面的例子展現了服務層(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 http://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>
複製代碼
下面的例子展現了數據訪問層 dao.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 http://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
類以及兩個數據訪問對象 JpaAccountDao
、JpaItemDao
(基於對象關係映射 JPA)。name
元素爲當前 Java Bean 的屬性名,ref
元素關聯着另外一個 Bean 定義的名稱。id
和 ref
元素的聯繫表現了關聯對象的依賴關係。請在 Dependencies 章節查看對象依賴的詳細內容。
組成 XML 配置元數據
在多個 XML 文件中定義 bean 是頗有用的。一般每一個單獨的 XML 文件配置文件,表明着您架構中的某個邏輯層次或模塊。
你可使用應用上下文構造器來加載多個 XML 配置文件。正如前文所述,這個構造器使用多個 Resource
路徑。或者您也可使用一個或多個 <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>
複製代碼
上面的例子展現了,在 services.xml
messageSource.xml
themeSource.xml
這三個文件中加載額外的 bean 定義。全部的路徑都是相對於當前文件的,因此 services.xml
必定和當前文件在相同目錄或者 classpath,然而 messageSource.xml
themeSource.xml
必定在當前文件的下級目錄。**正如你看到的,第一個 / 是被忽略的。**既然這些路徑都是相對的,最好就不用第一個 /。被導入的文件內容,包括最頂級的 <beans>
元素,但必須符合 Spring Schema 格式。
能夠用 "../" 相對路徑來關聯父目錄中的文件,但不建議這麼作。這樣作的話,會使當前應用依賴外部的文件。這種引用尤爲不建議在
classpath
中使用:URLs(如classpath:../services.xml
)運行時 進程會選擇最近的 classpath 根目錄,而後在它的父目錄中尋找。classpath 配置修改可能會致使選擇錯誤的目錄。 您也可使用絕對路徑,如:file:C:/config/services.xml
或者classpath:/config/services.xml
。可是,請注意你正在將您應用程序的配置文件和絕對路徑綁定在一塊兒。一般狀況下,最好是爲這樣的絕對路徑有一個間接關聯,好比,經過${xxx}
替代符在運行時解析 JVM 參數。
命名空間自己提供了 import 指令。Spring 提供了除普通 bean 定義以外的其餘 XML 命名空間特性,如 context
和 util
,也可使用。
ApplicationContext
接口提供了獲取各類 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();
複製代碼
最靈活的變體是 GenericApplicationContext
,能夠與 reader 代理配合,好比與 XmlBeanDefinitionReader
一塊兒讀取 XML 配置文件:
GenericApplicationContext context = new GenericApplicationContext();
new XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml");
context.refresh();
複製代碼
您能夠應用同一個 ApplicationContext
讀取不一樣配置文件中的 bean 定義。能夠經過 getBean
方法獲取你定義 bean 的實例。ApplicationContext
接口有不少其餘方法來獲取 bean,但並不建議使用他們。實際上您的應用程序能夠不使用任何 getBean
方法,所以就不會依賴 Spring API。好比 Spring 集成 web 框架並提供了依賴注入,好比 Controller bean 等,讓您能夠經過 metadata(元數據,如 @Autowired)在指定 bean 上聲明依賴。