4.1 Spring beans的建立和配置(XML方式)
準備
//--Classes.java
package com.erick.d1.hello;
public class Classes {
private String name;
private int number;
public Classes() { }
public Classes(String name, int number) {
super();
this.name = name;
this.number = number;
}
@Override
public String toString() {
return "Classes [name=" + name + ", number=" + number + "]";
}
//getter and setter
//...
}
//--Student.java
package com.erick.d1.hello;
public class Student {
private int age;
private String name;
//愛好
private List<String> hobby;
private Classes classes;
//getter and setter
//...
}
1. 建立bean
spring支援使用 構造器、靜態工廠、例項工廠 三種方式來建立bean
構造器建立bean
構造器建立bean是比較常見的,如果不採用構造注入,Spring會呼叫bean的午餐構造器來建立例項,
所以該Bean必須提供無參的構造器,使用這種方式配置時,class
屬性是必須的。
下面的配置(classes)使用了構造器建立,並且採用了構造注入方式
<!-- Beans.xml -->
<bean id="student" class ="com.erick.d1.hello.Student">
<property name="name" value="tom" />
<property name="age" value="12" />
<property name="classes" ref="classes"/>
</bean>
<bean id="classes" class="com.erick.d1.hello.Classes">
<!-- 構造器注入 -->
<constructor-arg type = "String" name="name">
<value>正音班1</value>
</constructor-arg>
<constructor-arg name="number">
<value>20</value>
</constructor-arg>
</bean>
靜態/例項工廠方法建立bean
後面會單獨介紹使用工廠方法建立Bean
2. 配置Bean
使用內部bean
<bean id="student" class="com.erick.d1.hello.Student">
<property name="name" value="tom" />
<property name="age" value="12" />
<property name="classes">
<!-- 內部bean不能被其他bean引用 -->
<bean class="com.erick.d1.hello.Classes">
<property name="name" value="08級一班"/>
<property name="number" value="31" />
</bean>
</property>
</bean>
級聯屬性配置
<bean id="student" class="com.erick.d1.hello.Student">
<property name="name" value="tom" />
<property name="age" value="12" />
<!-- 必須先有一個班級物件才能級聯賦值,否則報錯 -->
<property name="classes" ref="classes"/>
<property name="classes.name" value = "08級一班" />
<property name="classes.number" value="31" />
</bean>
配置集合屬性
<!-- List集合 -->
<property name="hobby">
<list>
<value>網球</value>
<value>網遊</value>
</list>
</property>
<!-- Map集合 -->
<property name="hobby">
<map>
<entry key="" value="" />
<entry key="" value="" />
</map>
</property>
<!-- propertie 配置 -->
<bean id = "dataSource" class="">
<property name="properties">
<props>
<prop key="user">root</prop>
<prop key="password">123</prop>
</props>
</property>
</bean>
集合配置時需要在
<property>
元素內。若想配置公用的需要新增util名稱空間
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="student" class="com.erick.d1.hello.Student">
<property name="name" value="tom" />
<property name="age" value="12" />
<property name="hobby" ref="hobby" />
</bean>
<util:list id="hobby">
<value>網球</value>
<value>網遊</value>
</util:list>
自動裝配
使用autowire
屬性進行自動裝配,自動裝配有三種方式:
- byName 通過屬性名裝配,屬性名必須完全匹配才能注入。
- byType 通過型別裝配,注入的型別若容器中有兩個bean則注入失敗。
- 構造器注入,比較複雜,不推薦使用。
<bean id="student" class="com.erick.d1.hello.Student" autowire="byType">
<property name="name" value="tom" />
<property name="age" value="12" />
</bean>
<bean id="classes" class="com.erick.d1.hello.Classes">
<constructor-arg type="String" name="name">
<value>正音班1</value>
</constructor-arg>
<constructor-arg name="number">
<value>20</value>
</constructor-arg>
</bean>
bean配置繼承
<bean id="studentAbs" abstract="true" class="com.erick.d1.hello.Student">
<property name="name" value="cat"/>
<property name="age" value="99"/>
</bean>
<bean id="student" autowire="byType" parent="studentAbs">
<property name="age" value="12" />
</bean>
- 繼承的是配置!類似模板,而非真正的父子關係。
- 子bean可以覆蓋從父bean中繼承的配置
- 父bean可以作為配置模板,也可以作為Bean例項。
abstract
屬性設定為true
,這樣spring容器不會例項化這個bean。 - 可以繼承的配置包括bean的屬性配置,但不是所有的屬性都會被繼承,比如
autowire
abstract
等。 - 當父bean屬性配置為
abstract=true
時class
屬性可以不指定,讓子bean指定。
依賴bean配置
<bean id="student" class="com.erick.d1.hello.Student" depends-on="classes">
<property name="name" value="tom" />
<property name="age" value="12" />
</bean>
若bean A 依賴於 bean B ,向容器請求bean A時,容器會先建立bean A,發現需要bean B注入,再建立bean B,並將其注入,然後將bean A返回。若指定
depends-on
則先建立bean B後建立bean A。
- Spring允許使用者通過
depends-on
屬性設定bean的前置依賴的bean,前置依賴的bean會在本bean例項化之前建立。 - 若前置依賴於多個bean,則可以通過逗號、空格的方式指定多個bean。
bean的別名
由於XML規範規定了
id
屬性必須由字母和數字組成,且只能以字母開頭,但在某些特殊情況下,例如與struts1整合時,必須為某些bean指定特殊標識名,測試就必須為其指定別名。
定義別名兩種方式:
- 設定
<bean/>
的屬性name
,若需要指定多個別名則可以在name
中使用 逗號、冒號或者空格來分隔。通過任何一個別名都可以訪問該bean例項。 - 通過
<alias/>
元素為已有的bean指定別名。
<!-- 為person bean指定三個別名 -->
<bean id="person" class="..." name="#abc,@123,abc*"/>
<!-- 為已有的person bean指指定別名 -->
<alias name="person" alias="jack"/>
<alias name="person" alias="jackee"/>
bean的作用域
使用scop
屬性來配置bean的作用域。
singleton:單例的,整個容器的生命週期內只建立一次該bean。預設情況是單例的。單例情況預設是非懶載入,即容器啟動時建立該bean。可以指定
lazy-init=true
改為懶載入。prototype:原型的,每次用到該bean時,容器都會建立一個新的bean。該模式載入模式為懶載入,並且修改
lazy-init=false
不會起任何作用。request:對於一次http請求,request作用域的bean將只生成一個例項。這意味著在同一次http請求內,每次請求該bean,得到的總是同一個例項。只有在Web應用中使用Spring時該作用域才真正有效。
session:對於一次http會話,session作用域的bean只生成一個例項,只有在Web應用中使用Spring時該作用域才真正有效。
global session:每個全域性的http session 對應一個bean例項,在典型的情況下,僅在使用portlet context的時候有效。只有在Web應用中使用Spring時該作用域才真正有效。
預設情況為
singleton
.為使request 和 session 作用域生效,必須將http請求物件繫結到為該請求提供服務的執行緒上,這使具有request 或 session作用域的bean例項能夠在後面的呼叫鏈中被訪問到。需要在web.xml中增加下面Listener配置,該Listener負責使request作用域生效。
<listener> <listener-class> org.springframework.web.context.request.RequestContextListener </listener-class> </listener>
若web應用直接使用spring MVC作為MVC框架,即用
SpringDispatcherServlet
或DispatcherPortlet
來攔截使用者請求,則無需這些額外配置,因為SpringDispatcherServlet
和DispatcherPortlet
已經處理了所有和請求有關的狀態處理。