一、bean基礎配置
對於bean的基礎配置如下
<bean id="" class=""/>
其中,bean標籤的功能、使用方式以及id和class屬性的作用,我們通過一張圖來描述下
思考:
-
class屬效能不能寫介面如
BookDao
的類全名呢?
答案肯定是不行,因為介面是沒辦法建立物件的。
-
前面提過為bean設定id時,id必須唯一,但是如果由於命名習慣而產生了分歧後,該如何解決?
在解決這個問題之前,我們需要準備下開發環境,內容如下:
二、bean的name屬性
環境準備好後,接下來就可以在這個環境的基礎上來學習下bean的別名配置,
首先來看下別名的配置說明:
步驟1:配置別名
開啟spring的配置檔案applicationContext.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">
<!--name:為bean指定別名,別名可以有多個,使用逗號,分號,空格進行分隔-->
<bean id="bookService" name="service service4 bookEbi" class="com.itheima.service.impl.BookServiceImpl">
<property name="bookDao" ref="bookDao"/>
</bean>
<!--scope:為bean設定作用範圍,可選值為單例singloton,非單例prototype-->
<bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl"/>
</beans>
說明:Ebi全稱Enterprise Business Interface,翻譯為企業業務介面
步驟2:根據名稱容器中獲取bean物件
public class AppForName {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//此處根據bean標籤的id屬性和name屬性的任意一個值來獲取bean物件
BookService bookService = (BookService) ctx.getBean("service4");
bookService.save();
}
}
步驟3:執行程式
測試結果為:
注意事項:
-
bean依賴注入的ref屬性指定bean,必須在容器中存在
-
如果不存在,則會報錯,如下:
這個錯誤大家需要特別關注下:
獲取bean無論是通過id還是name獲取,如果無法獲取到,將丟擲異常NoSuchBeanDefinitionException
遇到這樣的問題通常檢查名稱是否寫錯
三、bean作用範圍scope配置
關於bean的作用範圍是bean屬性配置的一個重點內容。看到這個作用範圍,我們就得思考bean的作用範圍是來控制bean哪塊內容的?
我們先來看下bean作用範圍的配置屬性
:
3.1 驗證IOC容器中物件是否為單例
驗證思路
同一個bean獲取兩次,將物件列印到控制檯,看列印出的地址值是否一致。
具體實現
-
建立一個AppForScope的類,在其main方法中來驗證
public class AppForScope { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); BookDao bookDao1 = (BookDao) ctx.getBean("bookDao"); BookDao bookDao2 = (BookDao) ctx.getBean("bookDao"); System.out.println(bookDao1); System.out.println(bookDao2); } }
-
列印,觀察控制檯的列印結果
-
結論:預設情況下,Spring建立的bean物件都是單例的
獲取到結論後,問題就來了,那如果我想建立出來非單例的bean物件,該如何實現呢?
3.2 配置bean為非單例
-
在Spring的配置檔案中,修改
<bean>
的scope屬性<bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl" scope=""/>
-
將scope設定為
singleton
<bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl" scope="singleton"/>
執行AppForScope,列印看結果
-
將scope設定為
prototype
<bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl" scope="prototype"/>
執行AppForScope,列印看結果
-
結論,使用bean的
scope
屬性可以控制bean的建立是否為單例:-
singleton
預設為單例 -
prototype
為非單例
-
3.3 scope使用後續思考
介紹完scope
屬性以後,我們來思考幾個問題:
-
為什麼bean預設為單例?
-
bean為單例的意思是在Spring的IOC容器中只會有該類的一個物件
-
bean物件只有一個就避免了物件的頻繁建立與銷燬,達到了bean物件的複用,效能高
-
-
bean在容器中是單例的,會不會產生執行緒安全問題?
-
如果物件是有狀態物件,即該物件有成員變數可以用來儲存資料的,
-
因為所有請求執行緒共用一個bean物件,所以會存線上程安全問題。
-
如果物件是無狀態物件,即該物件沒有成員變數沒有進行資料儲存的,
-
因方法中的區域性變數在方法呼叫完成後會被銷燬,所以不會存線上程安全問題。
-
-
哪些bean物件適合交給容器進行管理?
-
表現層物件 serviceImpl
-
業務層物件 service
-
資料層物件 dao
-
工具物件 util
-
-
哪些bean物件不適合交給容器進行管理?
-
封裝例項的域物件,因為會引發執行緒安全問題,所以不適合。
-