1 bean 對象的三種創建方式
1.1 通過構造函數創建bean對象
在默認情況下,當在spring配置文件中寫了一個bean標籤,並提供了 class 屬性,spring就會調用默認的構造函數創建對象。如果沒有默認構造函數,則對象創建失敗。
1.2 通過靜態工廠創建對象
package com.tzb.factory;
import com.tzb.service.IAccountService;
import com.tzb.service.impl.AccountServiceImpl;
/**
* 模擬一個靜態工廠
*/
public class StaticBeanFactory {
public static IAccountService getBean(){
return new AccountServiceImpl();
}
}
- bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--導入 spring 約束-->
<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">
<!-- bean definitions here -->
<!--配置業務層對象-->
<!--
bean標籤,讓spring讀取配置後創建對象
id:對象的唯一標識
-->
<bean id="accountService" class="com.tzb.service.impl.AccountServiceImpl">
</bean>
<!--配置持久層對象-->
<bean id="accountDao" class="com.tzb.dao.impl.IAccountDaoImpl"></bean>
<!--靜態工廠創建
factory-method: 指定創建 bean 對象的方法,可以是靜態,也可以不是
-->
<bean id="staticAccountService" class="com.tzb.factory.StaticBeanFactory" factory-method="getBean"></bean>
</beans>
1.3 通過實例工廠創建 bean 對象
package com.tzb.factory;
import com.tzb.service.IAccountService;
import com.tzb.service.impl.AccountServiceImpl;
/**
* 模擬一個靜態工廠
*/
public class InstanceBeanFactory {
public IAccountService getBean(){
return new AccountServiceImpl();
}
}
bean.xml
<!--實例工廠創建-->
<bean id="instanceFactory" class="com.tzb.factory.InstanceBeanFactory"></bean>
<bean id="instanceAccountService" factory-bean="instanceFactory" factory-method="getBean"></bean>
2 bean 對象的作用範圍
2.1 可以通過配置的方式指定
- 配置的屬性: bean 標籤的 scope 屬性
singleton
: 默認,單例的,【最常用】prototype
: 多例,每次創建新的實例request
: 一個對象在當前請求和請求轉發中可用session
: 會話範圍global-session
: 全局會話
3 bean 對象的生命週期
3.1 單例對象
- 出生:容器創建對象出生
- 活着:只要容器存在,對象就一直可用
- 死亡:容器銷燬
3.2 多例對象
- 出生:每次使用時,容器會創建對象
- 活着:只要對象在使用,就一直活着
- 死亡:垃圾回收器回收
4 spring依賴注入
4.1 注入方式(3種)
- 通過構造函數注入
- 通過 set 方法注入
構造函數注入
package com.tzb.service.impl;
import com.tzb.service.IAccountService;
import java.util.Date;
public class AccountServiceImpl implements IAccountService {
private String name;
private Integer age;
private Date birthday;
public AccountServiceImpl(String name, Integer age, Date birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
@Override
public void save() {
System.out.println("調用持久層的執行方法:" + name + "," + age + "," + birthday);
}
}
bean.xml
<!--使用構造函數注入
涉及的標籤:constructor-arg,bean 標籤內部的子標籤
標籤的屬性:
type:指定要注入的參數類型(在構造函數中)
index:指定要注入的參數在構造函數索引的位置
name:指定參數在構造函數中的名稱
value:指定注入的數據內容,只能指定基本數據類型和String
ref : 指定其他 bean類型數據,寫的是其他bean (存在於spring容器中)的id
-->
<bean id="nowDate" class="java.util.Date"></bean>
<bean id="accountService" class="com.tzb.service.impl.AccountServiceImpl">
<constructor-arg name="name" value="麥克"></constructor-arg>
<constructor-arg name="age" value="20"></constructor-arg>
<constructor-arg name="birthday" ref="nowDate"></constructor-arg>
</bean>
- 測試
public class Client {
/**
* 獲取 spring 的核心容器,並且根據bean的id獲取對象
* @param args
*/
public static void main(String[] args) {
// 獲取核心容器
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
// 根據 bean id 獲取對象
IAccountService accountService = (IAccountService) ac.getBean("accountService");
accountService.save();
}
}
使用 set 方法注入【常用】
public class AccountServiceImpl implements IAccountService {
private String name;
private Integer age;
private Date birthday;
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public void save() {
System.out.println("調用持久層的執行方法:" + name + "," + age + "," + birthday);
}
}
<!-- set 方法注入
涉及的標籤:property,該標籤也是要寫在 bean 標籤內部的子標籤
標籤的屬性:
name:指定的是set方法的名稱,set後面的部分
value:指定注入的數據內容,只能指定基本數據類型和String
ref : 指定其他 bean類型數據,寫的是其他bean (存在於spring容器中)的id
-->
<bean id="nowDate" class="java.util.Date"></bean>
<bean id="accountService" class="com.tzb.service.impl.AccountServiceImpl">
<property name="name" value="Mike"></property>
<property name="age" value="25"></property>
<property name="birthday" ref="nowDate"></property>
</bean>
使用 p 名稱空間注入
本質仍然是需要 set 方法,同時在配置文件導入 p 名稱空間
<bean id="nowDate" class="java.util.Date"></bean>
<bean id="accountService"
class="com.tzb.service.impl.AccountServiceImpl"
p:name="Mike"
p:age="26"
p:birthday-ref="nowDate">
</bean>
4.2 注入內容
- 基本數據類型和 String
- 其他 bean 類型
- 複雜類型(集合類)
集合類型注入
public class AccountServiceImpl implements IAccountService {
private String[] myStrs;
private List<String> myList;
private Set<String> mySet;
private Map<String, String> myMap;
private Properties myProps;
public void setMyStrs(String[] myStrs) {
this.myStrs = myStrs;
}
public void setMyList(List<String> myList) {
this.myList = myList;
}
public void setMyMap(Map<String, String> myMap) {
this.myMap = myMap;
}
public void setMyProps(Properties myProps) {
this.myProps = myProps;
}
public void setMySet(Set<String> mySet) {
this.mySet = mySet;
}
@Override
public void save() {
System.out.println(Arrays.toString(myStrs));
System.out.println(myList);
System.out.println(myMap);
System.out.println(mySet);
System.out.println(myProps);
}
}
- bean.xml
結構相同,標籤可以互換
<!--複雜數據類型注入-->
<bean id="accountService" class="com.tzb.service.impl.AccountServiceImpl">
<!--數組注入-->
<property name="myStrs">
<array>
<value>AAA</value>
<value>BBB</value>
</array>
</property>
<!--List-->
<property name="myList">
<list>
<value>AAA</value>
<value>BBB</value>
</list>
</property>
<!--Set-->
<property name="mySet">
<set>
<value>AAA</value>
<value>BBB</value>
</set>
</property>
<!--map注入-->
<property name="myMap">
<map>
<entry key="A" value="111"></entry>
<entry key="B">
<value>222</value>
</entry>
</map>
</property>
<!--properties注入-->
<property name="myProps">
<props>
<prop key="PA">111</prop>
<prop key="PB">222</prop>
</props>
</property>
</bean>