在Spring中,對象無需自己查找或創建與其所關聯的其他對象(解耦合)。
Spring容器負責創建應用程序中的bean並通過DI來協調Java對象之間的關係。
創建應用對象之間協作關係的行爲通常稱爲裝配(wiring),這也是依賴注入(DI)的本質。
總而言之,bean對象就是應用程序中的Java對象,Spring容器創建並封裝這些Java對象爲容器中的bean對象,在需要時自動注入到變量中,賦予對應Java對象的實例。
bean
Spring配置bean的三種方式
- 1.在XML中進行顯式配置。
- 2.在Java中進行顯式配置。
- 3.隱式的bean發現機制和自動裝配。
本文以XML中的顯式配置介紹bean對象的創建方式、作用範圍、生命週期等。
創建bean的方式
1 通過構造函數創建Java對象對應的bean
1.1 無參構造函數(默認構造函數)
<bean id="accountService" class="com.simple.service.impl.AccountServiceImpl" ></bean>
如上,通過AccountServiceImpl
的默認構造函數創建了AccountServiceImpl
實例化的bean對象。在Java代碼中定義的 AccountServiceImpl 類或其父類對象變量,會根據變量名對應bean的id自動注入。
1.1 帶參構造函數
<bean id="accountDao" class="com.simple.Dao.impl.AccountDaoImpl" ></bean>
<bean id="accountService" class="com.simple.service.impl.AccountServiceImpl" >
<constructor-arg ref="accountDao"></constructor-arg>
<constructor-arg value="#{T(其他各種類型,如string等等)}"></constructor-arg>
</bean>
accountDao
代表在AccountServiceImpl
類構造函數中需要注入的Java對象,ref 屬性的值爲該Java對象對應的bean的id值;#{T}
是Spring中的EL表達式,T表示構造函數中帶有的其他類型參數(基本類型,如String等等)。
2 使用普通工廠中的方法創建對象,並存入指定的bean
使用某個工廠類中的方法創建Java對象,並存入spring容器。
工廠類:
public class InitFactory {
public IAccountService getAccountService(){
return new AccountServiceImpl();
}
}
XML配置:
<bean id="initFactory" class="com.simple.factory.InitFactory"></bean>
<bean id="accountService" factory-bean="initFactory" factory-method="getAccountService"></bean>
3 使用工廠中的靜態方法創建對象,並存入指定的bean
使用某個類中的靜態方法創建Java對象,並存入spring容器。由於使用的是工廠中的靜態方法,所以不需要實例化工廠。
工廠類:
public class staticFactory {
public static IAccountService getAccountService(){
return new AccountServiceImpl();
}
}
XML配置:
<bean id="accountService" class="com.simple.factory.staticFactory" factory-method="getAccountService"></bean>
上述三種創建bean的方式中,一般使用第1種方法通過構造函數創建bean。
bean的作用範圍
bean的作用範圍由 bean 標籤的 scope 屬性來指定。其屬性值包括:
屬性值 | 說明 |
---|---|
singleton | 默認值,指定bean爲單例的 |
prototype | 指定bean爲多例的 |
request | web項目中,作用於request域 |
session | web項目中,作用於session域 |
global-session | web項目中,作用於集羣環境的session域;若不是集羣環境,則相當於session |
一般常用的是 singleton
,即單例的。
單例的bean表示Spring容器中該bean只有一個對應的實例化Java對象;多例的bean表示Spring容器中該bean可以有對應類多個實例化Java對象(可通過其存儲地址區分)。
bean對象的生命週期
1 單例bean
- 默認情況下,Spring讀取XML配置文件創建Spring容器時bean對象就會被創建
- 在創建對象時,先執行對象的構造方法,然後調用bean標籤的
init-method="..."
屬性值中指定的方法 - 在Spring容器銷燬時,單例bean隨之消亡。bean消亡即對象被銷燬時,會調用bean標籤的
destroy-method="..."
屬性值中指定的方法 - 可以設置bean標籤的
lazy-init="true"
使該對象在第一次被訪問時才創建
XML配置:創建單例bean,指定init-method="..."
和destroy-method="..."
屬性
<bean id="accountService" class="com.simple.service.impl.AccountServiceImpl"
scope="singleton" init-method="init" destroy-method="destory">
</bean>
AccountServiceImpl 類:
public class AccountServiceImpl implements IAccountService {
//默認無參構造器
public AccountServiceImpl() {
System.out.println("對象已創建!");
}
public void saveAccount() {
System.out.println("Service中的saveAccount方法執行了!!");
}
//初始時執行方法
public void init(){
System.out.println("對象初始化了!!!");
}
//銷燬時執行方法
public void destory(){
System.out.println("對象銷燬了!!!");
}
}
測試單例bean的生命週期:
public class Client {
public static void main(String[] args) {
//1.獲取Spring核心容器對象
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); //bean.xml放在根目錄下,所有可以直接寫文件名
//2.根據id獲取bean對象
//可以使用強制類型轉換
//IAccountService as = (IAccountService) ac.getBean("accountService");
//也可以指定對象類型
IAccountService as = ac.getBean("accountService",IAccountService.class);
//查看創建的as對象
System.out.println(as);
//執行as對象的方法
as.saveAccount();
//手動銷燬Spring容器,查看as對象消亡過程
ac.close();
System.out.println("結束!");
}
}
結果如下:
2 多例bean
- Spring讀取XML配置文件創建Spring容器時,不會立刻創建多例bean對應的對象
- 在每一次訪問這個多例bean對應的對象的時,spring容器都會創建該對象,並且調用
init-method=".."
屬性值中所指定的方法 - Spring容器銷燬時,多例bean對應創建的對象也不會消亡。因爲是多例的(該類型的對象可以有多個),所以在Spring容器創建該對象並將它賦予給Java變量後,該對象就由Java的進行管理,銷燬該對象也由垃圾回收機制進行回收。spring容器一旦把這個對象交給Java之後,就不再管理這個對象了