Spring之Bean的建立和裝配
前言
最近在重溫Spring,因此決定寫一系列的關於Spring學習的部落格,一是為了加深自己的理解,二來希望能幫助更多的朋友掌握Spring。我用到的Spring版本是3.1.1。
Spring建立Bean
Bean應該說是Spring中最基本的配置單位了,任何的操作都離不開Bean(好像是廢話哈)。記得剛開始接觸JavaEE的時候,看網上的教程通篇都是Bean啊Bean的,當時真是不知道Bean是何方神聖,英語不好還特意查了字典,發現Bean是豆子。。。這樣就更難理解了。在我的理解中Bean就是一個類,在Spring中通過元素宣告一個Bean,當合適的時候Spring容器來將這個Bean例項化,然後管理它的生命週期。
宣告Bean
宣告Bean很很簡單,首先在名稱空間中新增Bean的引用,一般類似下面這樣:
<?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" >
</beans>
之後就可以在配置檔案中自由的定義Bean了(友情提示:使用IntelliJ IDEA新增相應的名稱空間後可以自動帶出能出現的元素)。
為了下面講解方便,我先寫兩個類–經典的員工Employee和部門Department:
Employee.java
public class Employee {
private String name;
private Date birthDate;
private int level;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
}
Department .java
public class Department {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
上面已經新增過Bean的名稱空間了,因此我們就可以定義一個Employee和Department了:
<bean id="employee" class="com.stream.spring.bean.entity.Employee" />
<bean id="dept" class="com.stream.spring.bean.entity.Department" />
bean元素有幾個屬性值得注意:
- id或者name,指定Bean的名字。需要注意的是id是Bean的唯一標誌,而name可以有多個,並且在定義name的時候可以用任意的空格,逗號或者分號做分割。
- scope指定Bean的作用域。scope有五個可選值:singleton,prototype,request,session,global session。singleton是Spring預設的值,使用這個作用域的Bean,在容器中只有一個例項,從容器啟動,到第一次被請求而例項化開始,只要容器不銷燬或退出,該例項就會一直存活。prototype是多例項,對於每個請求都會返回一個例項。剩下的三個只適用於Web程式。
- init-method和destroy-method分別指定初始化方法和銷燬方法。全域性的初始化方法和銷燬方法在beans元素上定義default-init-method和default-destroy-method。
- factory-method通過工廠方法例項化Bean。
- autowire屬性指定Bean中屬性自動裝配時的查詢方式。
注入Bean的屬性
Spring注入Bean屬性有兩種方式:構造器注入和setter方法注入。
構造器注入
構造器注入使用constructor-arg標籤
<bean id="employee" class="com.stream.spring.bean.entity.Employee">
<constructor-arg name="name" value="stream" index="0"/>
</bean>
name是構造器方法的引數,index是引數的位置,當注入的是Bean時可以使用ref屬性。當使用構造器方法注入的時候,constructor-arg列表個數要個構造方法的引數個數一致,如下:
public Employee(String name,int level){
this.name = name;
this.level = level;
System.out.println("name,level");
}
/*public Employee(String name){
this.name = name;
System.out.println("name");
}*/
public Employee(int level){
this.level = level;
}
在Employee的構造方法中沒有對應的只有一個引數的構造方法,這樣在例項化Bean的時候會報錯:
Unsatisfied dependency expressed through constructor argument with index 1 of type [int]: Ambiguous constructor argument types - did you specify the correct bean references as constructor arguments?
另外需要注意的是如果沒有無參構造方法,那麼在裝配Bean屬性的時候必須要有構造器注入,否則會報錯。
setter方法注入
setter方法注入使用property標籤:
<bean id="employee" class="com.stream.spring.bean.entity.Employee">
<property name="name" value="Stream" />
</bean>
和構造器注入類似,name是Bean的屬性名,當需要注入Bean時可以用ref屬性。
setter方法只要保證在java類中有對應的setter方法即可,對順序和個數沒有限制。
裝配集合
當裝配的屬性是基本資料型別時可以直接使用value屬性,當引用其它Bean時使用ref屬性,當屬性是集合時Spring也提供了對應的方法。
Spring提供了4種類型的集合配置元素:
元素名稱 | 用途 | 宣告方式 |
---|---|---|
list | 裝配list型別的值,允許重複 | |
set | 裝配set型別的值,不允許重複 | |
map | 裝配map型別的值,key和value可以是任意型別 | |
props | 裝配properties型別的值,key和value必須都是String型別 |
裝配空值
可以使用標籤來顯式的指定空值。