一、bean 標簽和管理對象細節
1.1 bean 標簽
作用:
用於配置對象讓spring來創建的。
默認情況下它調用的是類中的無參構造函數。如果沒有無參構造函數則不能創建成功。
屬性:
id:給對象在容器中提供一個唯一標識。用於獲取對象。
class:指定類的權限定類名。用於反射創建對象。默認情況下調用無參構造函數。
scope:指定對象的作用范圍。
* singleton:默認值,單例的。
* prototype:多例的
init-method:指定類中的初始化方法名稱。
destory-method:指定類中銷毀方法名稱。
1.2 bean的作用范圍和生命周期
單列對象:scope="singleton"
一個應用只有一個對象的實例。它的作用范圍就是整個引用。
生命周期:
對象出生:當應用加載時,創建容器時,對象就被創建了。
對象活着:只有容器在,對象一直活着。
對象死亡:當應用卸載,銷毀容器時,對象就被銷毀了。
多例對象:scope="prototype"
每次訪問對象時,都會重新創建對象實例。
生命周期:
對象出生:當使用對象時,創建新的對象實例。
對象活着:只要對象在使用中,就一直活着。
對象死亡:當對象長時間不用時,被java的垃圾回收器回收了。
演示:單例和多例對象
第一步:編寫IUserService接口
1 package com.justnow.service; 2 3 public interface IUserService { 4 public void findAll(); 5 }
第二步:編寫UserServiceImpl實現類
1 package com.justnow.service.impl; 2 3 import com.justnow.service.IUserService; 4 5 public class UserServiceImpl implements IUserService { 6 7 public void findAll() { 8 System.out.println("假裝打印了數據庫中的所有數據"); 9 } 10 }
第三步:編寫spring配置文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans.xsd"> 6 <!--配置 service --> 7 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" scope="singleton"/> 8 </beans>
這里配置scope為單例對象
第四步:測試
1 package com.justnow.test; 2 3 import com.justnow.service.IUserService; 4 import org.junit.Test; 5 import org.springframework.context.support.ClassPathXmlApplicationContext; 6 7 public class Test01 { 8 @Test 9 public void testBean(){ 10 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 11 IUserService userService = (IUserService) context.getBean("userService"); 12 IUserService userService1 = (IUserService) context.getBean("userService"); 13 System.out.println(userService); 14 System.out.println(userService1); 15 } 16 }
單例測試結果:
userService和userService2,打印出來的結果是一致的!
雙例測試結果:
修改scope為"prototype"
1.3 實例化bean的三種方式
第一種方式:使用默認無參構造函數
會根據默認無參構造函數來創建類對象。如果bean中沒有默認無參構造函數,將會創建失敗。
如:
1 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" />
此時UserServiceImpl中必須有無參的構造函數。
第二種方式:spring管理靜態工廠-使用靜態工廠的方法創建對象
模擬一個靜態工廠,創建業務層實現類
1 package com.justnow.factory; 2 3 import com.justnow.service.IUserService; 4 import com.justnow.service.impl.UserServiceImpl; 5 6 public class StaticFactory { 7 public static IUserService createUserService(){ 8 return new UserServiceImpl(); 9 } 10 }
bean的配置,使用StaticFactory類中的靜態方法createUserService創建對象,並存入spring容器:
id 屬性:指定bean的id,用於從容器中獲取
class屬性:指定靜態工廠的全限定類名
factory-method 屬性:指定生產對象的靜態方法
1 <bean id="userService" class="com.justnow.factory.StaticFactory" factory-method="createUserService" />
第三種方式:spring管理實例工廠-使用實例工廠的方法創建對象
先把工廠的創建交給spring來管理。然后在使用工廠的bean來調用里面的方法
factory-bean屬性:用來指定實例工廠beand的id。
factory-method屬性:用於指定實例工廠中創建對象的方法。
模擬一個實例工廠,創建業務層實現類
此工廠創建對象,必須現有工廠實例對象,再調用方法
1 package com.justnow.factory; 2 3 import com.justnow.service.IUserService; 4 import com.justnow.service.impl.UserServiceImpl; 5 6 /** 7 * 模擬一個實例工廠,創建業務層實現類 8 * 此工廠創建對象,必須有工廠實例對象,再調用方法 9 */ 10 public class InstanceFactory { 11 public IUserService createUserService(){ 12 return new UserServiceImpl(); 13 } 14 }
bean的配置文件
<!--第三種方式,spring管理實例工廠,使用實例工廠的方法創建對象--> <bean id="instanceFactory" class="com.justnow.factory.InstanceFactory"/> <bean id="userService" factory-bean="instanceFactory" factory-method="createUserService" />
https://github.com/justn0w/javawebdemo/tree/master/spring/Spring_demo2
d20c371406409b204c554c0a41c91ad5b6b86de1
二、spring的依賴注入
2.1 什么是依賴注入:
依賴注入:Dependency Injection。它是spring框架核心IoC的具體實現。
我們的程序在編寫時,通過控制反轉,把對象的創建交給了spring,但是在代碼中不可能出現沒有依賴的情況。IoC解耦只是降低他們的依賴關系。
但不會消除。例如:我們的業務層仍會調用持久層的方法。簡單的說就是spring框架把持久層對象傳入業務層,而不用我們自己去獲取。
2.2 通過構造函數實現依賴注入
使用類中的構造函數,給成員變量賦值。賦值操作是由spring框架來為我們注入的。
UserServiceImpl實現類:
該類共有三個屬性,分別是name,age,birthday;
1 package com.justnow.service.impl; 2 3 import com.justnow.service.IUserService; 4 5 import java.util.Date; 6 7 public class UserServiceImpl implements IUserService { 8 9 private String name; 10 private Integer age; 11 private Date birthdy; 12 13 public UserServiceImpl() { 14 } 15 16 public UserServiceImpl(String name, Integer age, Date birthdy){ 17 this.name = name; 18 this.age = age; 19 this.birthdy = birthdy; 20 } 21 22 public void save(){ 23 System.out.println(name+","+age+","+birthdy); 24 } 25 26 /* public void findAll() { 27 System.out.println("假裝打印了數據庫中的所有數據"); 28 }*/ 29 }
在配置文件中賦值:
applicationContext.xml
1 <!--通過構造函數實現依賴注入--> 2 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" > 3 <constructor-arg name="name" value="張三"></constructor-arg> 4 <constructor-arg name="age" value="18"></constructor-arg> 5 <constructor-arg name="birthdy" ref="now"></constructor-arg> 6 </bean> 7 <bean id="now" class="java.util.Date" />
使用構造函數的方式,給service中的屬性賦值
要求:類中需要提供一個對應參數列表的構造函數
標簽:constructor-arg
屬性:index:指定參數在構造函數列表的索引位置
type:指定參數在構造函數中的數據類型
name:指定參數在構造函數中的名稱
value:給name屬性賦值,前提是基本數據類型和String類型
ref:同樣的是給name賦值,但是該值是bean類型,必須在配置文件中配置。如上例中的id為now的bean標簽
本小節代碼:
https://github.com/justn0w/javawebdemo/tree/master/spring/Spring_demo2
2e64f8d7cf0a7a1f710e8abfc3d9707653b5063a
2.2 set 方法注入
在UserServiceImpl實現類中,設置屬性的set的方法即可代碼,如下:
1 package com.justnow.service.impl; 2 3 import com.justnow.service.IUserService; 4 5 import java.util.Date; 6 7 public class UserServiceImpl implements IUserService { 8 9 private String name; 10 private Integer age; 11 private Date birthdy; 12 13 //set 方法注入 14 public void setName(String name) { 15 this.name = name; 16 } 17 18 public void setAge(Integer age) { 19 this.age = age; 20 } 21 22 public void setBirthdy(Date birthdy) { 23 this.birthdy = birthdy; 24 } 25 26 public void save(){ 27 System.out.println(name+","+age+","+birthdy); 28 } 29 30 }
同時還需要修改spring的配置文件
1 <!--通過set方法實現依賴注入--> 2 <!-- 通過配置文件給 bean 中的屬性傳值:使用 set 方法的方式 3 涉及的標簽: 4 property 5 屬性: 6 name:找的是類中 set 方法后面的部分 7 ref:給屬性賦值是其他 bean 類型的 8 value:給屬性賦值是基本數據類型和 string 類型的 9 實際開發中,此種方式用的較多。 10 --> 11 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl"> 12 <property name="name" value="test"/> 13 <property name="age" value="21"/> 14 <property name="birthdy" ref="now" /> 15 </bean> 16 17 <bean id="now" class="java.util.Date" />
測試結果:
https://github.com/justn0w/javawebdemo/tree/master/spring/Spring_demo2
fe6038b18cff7d32c1b4515bf53bea9c8b0bdd0e
2.2 使用p名稱空間注入數據
在xml中導入p名稱空間,使用p:propertyName來注入數據,本質仍然是調用類中的set方法實現注入功能。
所以,UserServiceIpml實現類,不需要改變。只需要修改spring的配置文件即可
第一步:修改xml的命名空間,即添加p命名空間
添加了一句:
xmlns:p="http://www.springframework.org/schema/p"
第二步:在bean中使用p標簽給屬性賦值
1 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" p:name="testp" p:age="23" p:birthdy-ref="now"/> 2 <bean id="now" class="java.util.Date" />
測試結果:
47e50fff82f0cee3155226f620a00989da3828a6
2.3 注入集合屬性
考慮到某些情況下需要一些類型為集合的屬性,接下來就演示下,如何注入集合屬性的。其本質還是通過set方法注入屬性的
第一步:在實現類中添加數組、List、set、Map、Properties等數據類型的屬性。
1 package com.justnow.service.impl; 2 3 import com.justnow.service.IUserService; 4 5 import java.util.*; 6 7 public class UserServiceImpl2 implements IUserService { 8 9 private String[] myStrs; 10 private List<String> myList; 11 private Set<String> mySet; 12 private Map<String, String> myMap; 13 private Properties myProps; 14 15 public void setMyStrs(String[] myStrs) { 16 this.myStrs = myStrs; 17 } 18 19 public void setMyList(List<String> myList) { 20 this.myList = myList; 21 } 22 23 public void setMySet(Set<String> mySet) { 24 this.mySet = mySet; 25 } 26 27 public void setMyMap(Map<String, String> myMap) { 28 this.myMap = myMap; 29 } 30 31 public void setMyProps(Properties myProps) { 32 this.myProps = myProps; 33 } 34 35 36 public void save() { 37 System.out.println(Arrays.toString(myStrs)); 38 System.out.println(myList); 39 System.out.println(mySet); 40 System.out.println(myMap); 41 System.out.println(myProps); 42 } 43 }
第二步:修改spring配置文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:p="http://www.springframework.org/schema/p" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans.xsd"> 7 <!--配置 service --> 8 <!-- 第一種方式,使用默認無參構造函數 9 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" scope="prototype"/> 10 --> 11 <!--第二種方式,spring管理靜態工廠-使用靜態工廠的方法對象創建--> 12 <!-- 13 <bean id="userService" class="com.justnow.factory.StaticFactory" factory-method="createUserService" /> 14 --> 15 <!--第三種方式,spring管理實例工廠,使用實例工廠的方法創建對象--> 16 <!-- 17 <bean id="instanceFactory" class="com.justnow.factory.InstanceFactory"/> 18 <bean id="userService" factory-bean="instanceFactory" factory-method="createUserService" /> 19 --> 20 21 <!--通過構造函數實現依賴注入--> 22 <!-- 23 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" > 24 <constructor-arg name="name" value="張三"></constructor-arg> 25 <constructor-arg name="age" value="18"></constructor-arg> 26 <constructor-arg name="birthdy" ref="now"></constructor-arg> 27 </bean> 28 <bean id="now" class="java.util.Date" /> 29 --> 30 <!--通過set方法實現依賴注入--> 31 <!-- 通過配置文件給 bean 中的屬性傳值:使用 set 方法的方式 32 涉及的標簽: 33 property 34 屬性: 35 name:找的是類中 set 方法后面的部分 36 ref:給屬性賦值是其他 bean 類型的 37 value:給屬性賦值是基本數據類型和 string 類型的 38 實際開發中,此種方式用的較多。 39 40 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl"> 41 <property name="name" value="test"/> 42 <property name="age" value="21"/> 43 <property name="birthdy" ref="now" /> 44 </bean> 45 46 <bean id="now" class="java.util.Date" /> 47 --> 48 <!--使用p命名空間--> 49 <!-- 50 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" p:name="testp" p:age="23" p:birthdy-ref="now"/> 51 <bean id="now" class="java.util.Date" /> 52 --> 53 <!-- 注入集合數據 54 List 結構的: 55 array,list,set 56 Map 結構的 57 map,entry,props,prop 58 --> 59 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl2"> 60 <!-- 在注入集合數據時,只要結構相同,標簽可以互換 --> 61 <!-- 給數組注入數據 --> 62 <property name="myStrs"> 63 <array> 64 <value>AAA</value> 65 <value>BBB</value> 66 <value>CCC</value> 67 </array> 68 </property> 69 <!-- 注入 list 集合數據 --> 70 <property name="myList"> 71 <list> 72 <value>AAA</value> 73 <value>BBB</value> 74 <value>CCC</value> 75 </list> 76 </property> 77 <!-- 注入 set 集合數據 --> 78 <property name="mySet"> 79 <set> 80 <value>AAA</value> 81 <value>BBB</value> 82 <value>CCC</value> 83 </set> 84 </property> 85 <!-- 注入 Map 數據 --> 86 <property name="myMap"> 87 <props> 88 <prop key="testA">aaa</prop> 89 <prop key="testB">bbb</prop> 90 </props> 91 </property> 92 <!-- 注入 properties 數據 --> 93 <property name="myProps"> 94 <map> 95 <entry key="testA" value="aaa"></entry> 96 <entry key="testB"> 97 <value>bbb</value> 98 </entry> 99 </map> 100 </property> 101 </bean> 102 </beans>
77a345e6da51295e1aa4c5e8c25038e23da3f6ec
總結:
1、這些內容在將來的開發過程中會很少用到,但是,還是梳理一下。