被稱做 bean 的對象是構成應用程序的支柱也是由 Spring IoC 容器管理的。bean 是一個被實例化,組裝,並經過 Spring IoC 容器所管理的對象。這些 bean 是由用容器提供的配置元數據建立的,例如,已經在先前章節看到的,在 XML 的表單中的 定義。java
bean 定義包含稱爲配置元數據的信息,下述容器也須要知道配置元數據:nginx
如何建立一個 beanweb
bean 的生命週期的詳細信息spring
上述全部的配置元數據轉換成一組構成每一個 bean 定義的下列屬性。session
屬性 | 描述 |
---|---|
class | 這個屬性是強制性的,而且指定用來建立 bean 的 bean 類。 |
name | 這個屬性指定惟一的 bean 標識符。在基於 XML 的配置元數據中,你可使用 ID 和/或 name 屬性來指定 bean 標識符。 |
scope | 這個屬性指定由特定的 bean 定義建立的對象的做用域,它將會在 bean 做用域的章節中進行討論。 |
constructor-arg | 它是用來注入依賴關係的,並會在接下來的章節中進行討論。 |
properties | 它是用來注入依賴關係的,並會在接下來的章節中進行討論。 |
autowiring mode | 它是用來注入依賴關係的,並會在接下來的章節中進行討論。 |
lazy-initialization mode | 延遲初始化的 bean 告訴 IoC 容器在它第一次被請求時,而不是在啓動時去建立一個 bean 實例。 |
initialization 方法 | 在 bean 的全部必需的屬性被容器設置以後,調用回調方法。它將會在 bean 的生命週期章節中進行討論。 |
destruction 方法 | 當包含該 bean 的容器被銷燬時,使用回調方法。它將會在 bean 的生命週期章節中進行討論。 |
Bean 與 Spring 容器的關係框架
下圖表達了Bean 與 Spring 容器之間的關係:this
Spring IoC 容器徹底由實際編寫的配置元數據的格式解耦。有下面三個重要的方法把配置元數據提供給 Spring 容器:spa
基於 XML 的配置文件prototype
基於註解的配置code
提示:對於基於 XML 的配置,Spring 2.0 之後使用 Schema 的格式,使得不一樣類型的配置擁有了本身的命名空間,是配置文件更具擴展性。
你已經看到了如何把基於 XML 的配置元數據提供給容器,可是讓咱們看看另外一個基於 XML 配置文件的例子,這個配置文件中有不一樣的 bean 定義,包括延遲初始化,初始化方法和銷燬方法的:
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <beans xmlns="http://www.springframework.org/schema/beans" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 7 8 <!-- A simple bean definition --> 9 <bean id="..." class="..."> 10 <!-- collaborators and configuration for this bean go here --> 11 </bean> 12 13 <!-- A bean definition with lazy init set on --> 14 <bean id="..." class="..." lazy-init="true"> 15 <!-- collaborators and configuration for this bean go here --> 16 </bean> 17 18 <!-- A bean definition with initialization method --> 19 <bean id="..." class="..." init-method="..."> 20 <!-- collaborators and configuration for this bean go here --> 21 </bean> 22 23 <!-- A bean definition with destruction method --> 24 <bean id="..." class="..." destroy-method="..."> 25 <!-- collaborators and configuration for this bean go here --> 26 </bean> 27 28 <!-- more bean definitions go here --> 29 30 </beans>
在上述示例中:
①xmlns="http://www.springframework.org/schema/beans",默認命名空間:它沒有空間名,用於Spring Bean的定義;
②xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance",xsi命名空間:這個命名空間用於爲每一個文檔中命名空間指定相應的Schema樣式文件,是標準組織定義的標準命名空間。
當在 Spring 中定義一個 bean 時,你必須聲明該 bean 的做用域的選項。例如,爲了強制 Spring 在每次須要時都產生一個新的 bean 實例,你應該聲明 bean 的做用域的屬性爲 prototype。同理,若是你想讓 Spring 在每次須要時都返回同一個bean實例,你應該聲明 bean 的做用域的屬性爲 singleton。
Spring 框架支持如下五個做用域,分別爲singleton、prototype、request、session和global session,5種做用域說明以下所示,
注意,若是你使用 web-aware ApplicationContext 時,其中三個是可用的。
做用域 | 描述 |
---|---|
singleton | 在spring IoC容器僅存在一個Bean實例,Bean以單例方式存在,默認值 |
prototype | 每次從容器中調用Bean時,都返回一個新的實例,即每次調用getBean()時,至關於執行newXxxBean() |
request | 每次HTTP請求都會建立一個新的Bean,該做用域僅適用於WebApplicationContext環境 |
session | 同一個HTTP Session共享一個Bean,不一樣Session使用不一樣的Bean,僅適用於WebApplicationContext環境 |
global-session | 通常用於Portlet應用環境,該運用域僅適用於WebApplicationContext環境 |
本章將討論前兩個範圍,當咱們將討論有關 web-aware Spring ApplicationContext 時,其他三個將被討論。
singleton 是默認的做用域,也就是說,當定義 Bean 時,若是沒有指定做用域配置項,則 Bean 的做用域被默認爲 singleton。
當一個bean的做用域爲Singleton,那麼Spring IoC容器中只會存在一個共享的bean實例,而且全部對bean的請求,只要id與該bean定義相匹配,則只會返回bean的同一實例。
也就是說,當將一個bean定義設置爲singleton做用域的時候,Spring IoC容器只會建立該bean定義的惟一實例。
Singleton是單例類型,就是在建立起容器時就同時自動建立了一個bean的對象,無論你是否使用,他都存在了,每次獲取到的對象都是同一個對象。
注意,Singleton做用域是Spring中的缺省做用域。你能夠在 bean 的配置文件中設置做用域的屬性爲 singleton,以下所示:
1 <!-- A bean definition with singleton scope --> 2 <bean id="..." class="..." scope="singleton"> 3 <!-- collaborators and configuration for this bean go here --> 4 </bean>
這裏是 HelloWorld.java 文件的內容:
1 package com.tutorialspoint; 2 public class HelloWorld { 3 private String message; 4 public void setMessage(String message){ 5 this.message = message; 6 } 7 public void getMessage(){ 8 System.out.println("Your Message : " + message); 9 } 10 }
下面是 MainApp.java 文件的內容:
1 package com.tutorialspoint; 2 import org.springframework.context.ApplicationContext; 3 import org.springframework.context.support.ClassPathXmlApplicationContext; 4 public class MainApp { 5 public static void main(String[] args) { 6 ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml"); 7 HelloWorld objA = (HelloWorld) context.getBean("helloWorld"); 8 objA.setMessage("I'm object A"); 9 objA.getMessage(); 10 HelloWorld objB = (HelloWorld) context.getBean("helloWorld"); 11 objB.getMessage(); 12 } 13 }
下面是 singleton 做用域必需的配置文件 Beans.xml:
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <beans xmlns="http://www.springframework.org/schema/beans" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 7 8 <bean id="helloWorld" class="com.tutorialspoint.HelloWorld" 9 scope="singleton"> 10 </bean> 11 </beans>
一旦你建立源代碼和 bean 配置文件完成後,咱們就能夠運行該應用程序。若是你的應用程序一切都正常,將輸出如下信息:
Your Message : I'm object A Your Message : I'm object A
當一個bean的做用域爲Prototype,表示一個bean定義對應多個對象實例。Prototype做用域的bean會致使在每次對該bean請求(將其注入到另外一個bean中,或者以程序的方式調用容器的getBean()方法)
時都會建立一個新的bean實例。Prototype是原型類型,它在咱們建立容器的時候並無實例化,而是當咱們獲取bean的時候纔會去建立一個對象,並且咱們每次獲取到的對象都不是同一個對象。
根據經驗,對有狀態的bean應該使用prototype做用域,而對無狀態的bean則應該使用singleton做用域。
爲了定義 prototype 做用域,你能夠在 bean 的配置文件中設置做用域的屬性爲 prototype,以下所示:
1 <!-- A bean definition with singleton scope --> 2 <bean id="..." class="..." scope="prototype"> 3 <!-- collaborators and configuration for this bean go here --> 4 </bean>
1 package com.tutorialspoint; 2 3 public class HelloWorld { 4 private String message; 5 6 public void setMessage(String message){ 7 this.message = message; 8 } 9 10 public void getMessage(){ 11 System.out.println("Your Message : " + message); 12 } 13 }
下面是 MainApp.java 文件的內容:
1 package com.tutorialspoint; 2 import org.springframework.context.ApplicationContext; 3 import org.springframework.context.support.ClassPathXmlApplicationContext; 4 public class MainApp { 5 public static void main(String[] args) { 6 ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml"); 7 HelloWorld objA = (HelloWorld) context.getBean("helloWorld"); 8 objA.setMessage("I'm object A"); 9 objA.getMessage(); 10 HelloWorld objB = (HelloWorld) context.getBean("helloWorld"); 11 objB.getMessage(); 12 } 13 }
下面是 prototype 做用域必需的配置文件 Beans.xml:
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <beans xmlns="http://www.springframework.org/schema/beans" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 7 8 <bean id="helloWorld" class="com.tutorialspoint.HelloWorld" 9 scope="prototype"> 10 </bean> 11 12 </beans>
一旦你建立源代碼和 Bean 配置文件完成後,咱們就能夠運行該應用程序。若是你的應用程序一切都正常,將輸出如下信息:
Your Message : I'm object A Your Message : null
理解 Spring bean 的生命週期很容易。當一個 bean 被實例化時,它可能須要執行一些初始化使它轉換成可用狀態。一樣,當 bean 再也不須要,而且從容器中移除時,可能須要作一些清除工做。
儘管還有一些在 Bean 實例化和銷燬之間發生的活動,可是本章將只討論兩個重要的生命週期回調方法,它們在 bean 的初始化和銷燬的時候是必需的。
爲了定義安裝和拆卸一個 bean,咱們只要聲明帶有 init-method 和/或 destroy-method 參數的 。init-method 屬性指定一個方法,在實例化 bean 時,當即調用該方法。一樣,destroy-method 指定一個方法,只有從容器中移除 bean 以後,才能調用該方法。
Bean的生命週期能夠表達爲:Bean的定義——Bean的初始化——Bean的使用——Bean的銷燬
org.springframework.beans.factory.InitializingBean 接口指定一個單一的方法:
1 void afterPropertiesSet() throws Exception;
所以,你能夠簡單地實現上述接口和初始化工做能夠在 afterPropertiesSet() 方法中執行,以下所示:
1 public class ExampleBean implements InitializingBean { 2 public void afterPropertiesSet() { 3 // do some initialization work 4 } 5 }
在基於 XML 的配置元數據的狀況下,你可使用 init-method 屬性來指定帶有 void 無參數方法的名稱。例如:
1 <bean id="exampleBean" 2 class="examples.ExampleBean" init-method="init"/>
下面是類的定義:
1 public class ExampleBean { 2 public void init() { 3 // do some initialization work 4 } 5 }
org.springframework.beans.factory.DisposableBean 接口指定一個單一的方法:
void destroy() throws Exception;
所以,你能夠簡單地實現上述接口而且結束工做能夠在 destroy() 方法中執行,以下所示:
1 public class ExampleBean implements DisposableBean { 2 public void destroy() { 3 // do some destruction work 4 } 5 }
在基於 XML 的配置元數據的狀況下,你可使用 destroy-method 屬性來指定帶有 void 無參數方法的名稱。例如:
1 <bean id="exampleBean" 2 class="examples.ExampleBean" destroy-method="destroy"/>
下面是類的定義:
1 public class ExampleBean { 2 public void destroy() { 3 // do some destruction work 4 } 5 }
若是你在非 web 應用程序環境中使用 Spring 的 IoC 容器;例如在豐富的客戶端桌面環境中;那麼在 JVM 中你要註冊關閉 hook。這樣作能夠確保正常關閉,爲了讓全部的資源都被釋放,能夠在單個 beans 上調用 destroy 方法。
建議你不要使用 InitializingBean 或者 DisposableBean 的回調方法,由於 XML 配置在命名方法上提供了極大的靈活性。
咱們在適當的位置使用 Eclipse IDE,而後按照下面的步驟來建立一個 Spring 應用程序:
步驟 | 描述 |
---|---|
1 | 建立一個名稱爲 SpringExample 的項目,而且在建立項目的 src 文件夾中建立一個包 com.tutorialspoint。 |
2 | 使用 Add External JARs 選項,添加所需的 Spring 庫,解釋見 Spring Hello World Example 章節。 |
3 | 在 com.tutorialspoint 包中建立 Java 類 HelloWorld 和 MainApp。 |
4 | 在 src 文件夾中建立 Beans 配置文件 Beans.xml。 |
5 | 最後一步是建立的全部 Java 文件和 Bean 配置文件的內容,並運行應用程序,解釋以下所示。 |
這裏是 HelloWorld.java 的文件的內容:
1 package com.tutorialspoint; 2 3 public class HelloWorld { 4 private String message; 5 6 public void setMessage(String message){ 7 this.message = message; 8 } 9 public void getMessage(){ 10 System.out.println("Your Message : " + message); 11 } 12 public void init(){ 13 System.out.println("Bean is going through init."); 14 } 15 public void destroy(){ 16 System.out.println("Bean will destroy now."); 17 } 18 }
下面是 MainApp.java 文件的內容。在這裏,你須要註冊一個在 AbstractApplicationContext 類中聲明的關閉 hook 的 registerShutdownHook() 方法。它將確保正常關閉,而且調用相關的 destroy 方法。
1 package com.tutorialspoint; 2 import org.springframework.context.support.AbstractApplicationContext; 3 import org.springframework.context.support.ClassPathXmlApplicationContext; 4 public class MainApp { 5 public static void main(String[] args) { 6 AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml"); 7 HelloWorld obj = (HelloWorld) context.getBean("helloWorld"); 8 obj.getMessage(); 9 context.registerShutdownHook(); 10 } 11 }
下面是 init 和 destroy 方法必需的配置文件 Beans.xml 文件:
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <beans xmlns="http://www.springframework.org/schema/beans" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 7 8 <bean id="helloWorld" 9 class="com.tutorialspoint.HelloWorld" 10 init-method="init" destroy-method="destroy"> 11 <property name="message" value="Hello World!"/> 12 </bean> 13 </beans>
一旦你建立源代碼和 bean 配置文件完成後,咱們就能夠運行該應用程序。若是你的應用程序一切都正常,將輸出如下信息:
Bean is going through init. Your Message : Hello World! Bean will destroy now.
若是你有太多具備相同名稱的初始化或者銷燬方法的 Bean,那麼你不須要在每個 bean 上聲明初始化方法和銷燬方法。框架使用 元素中的 default-init-method 和 default-destroy-method 屬性提供了靈活地配置這種狀況,以下所示:
1 <beans xmlns="http://www.springframework.org/schema/beans" 2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://www.springframework.org/schema/beans 4 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" 5 default-init-method="init" 6 default-destroy-method="destroy"> 7 8 <bean id="..." class="..."> 9 <!-- collaborators and configuration for this bean go here --> 10 </bean> 11 12 </beans>