Spring框架作為Bean的管理容器,其最經典最基礎的Bean配置方式就是純XML配置,這樣做使得結構清晰明了,適合大型項目使用。Spring的XML配置雖然很繁瑣,而且存在簡潔的注解方式,但讀懂XML配置文件對我們來說依然很重要,尚且對於老系統維護必不可少的面對XML配置。
下面通過案例來理解XML配置。
案例:(一個基礎的Bean)
public class Pet { private String petType; private String color ; public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String getPetType() { return petType; } public void setPetType(String petType) { this.petType = petType; } public String toString(){ return"petType: "+petType+" color: "+color; } }
public class User { String id; String name; String passWord; Pet pet; public Pet getPet() { return pet; } public void setPet(Pet pet) { this.pet = pet; } public User(){ System.out.println("spring 需要一個空參構造!"); } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassWord() { return passWord; } public void setPassWord(String passWord) { this.passWord = passWord; } @Override public String toString() { return "User{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", passWord='" + passWord + '\'' + ", pet=" + pet + '}'; } public void init(){ System.out.println("User初始化執行init方法!"); } public void userDestroy(){ System.out.println("userDestroy方法被執行!"); } }
import com.bing.tao.bean.User; import org.junit.jupiter.api.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; public class HelloSpring { /** * IOC的反轉:創建對象這份工作由我們自己執行反轉給spring幫我們執行; * IOC的控制:就是由spring幫我們負責創建銷毀對象,掌控對象的生命周期等,我們在需要使用對象的時候跟Spring申請即可; * IOC是一種編程思想,也是一種新的設計模式,它需要DI(依賴注入)技術的支持; * spring是一個容器,它將幫我們管理對象 */ @Test public void Test1(){ //根據spring配置文件獲取容器對象 //ApplicationContext 配置的所有bean都會在容器創建的時候被創建出來 //如果配置的bean較多,那么在創建容的時候,會產生內存過大的問題;這種情況在機器硬件性能較為落后的時候體現的比較明顯; //延遲加載 true就是創建容器時不加載配置的bean對象,在獲取的時候才創建; ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); User user= (User) applicationContext.getBean("user"); System.out.println("user: "+user); //通過getBean獲取配置好的user對象(程序員向spring容器要對象) user= applicationContext.getBean(User.class); System.out.println("user: "+user); applicationContext.close(); } }
重要的配置:(創建一個名字叫: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"> <!-- spring管理bean的XML,一個bean標簽表示一個bean。--> <!-- name屬性給bean取名,代碼中可以通過:applicationContext.getBean("user"); 獲取class--> <!-- class:是被管理對象的全包名,spring會通過這個包名來創建對象 --> <!-- scope 屬性,控制對象的單例還是多例,prototype多例--> <!-- 在web環境下,如果scope屬性為request 那么這個對象被創建出來 他的生命周期會與request請求一致--> <!-- session 同理 ,生命周期與session一致 --> <!-- lazy-init 延遲加載,獲取bean 的時候才加載 ,否則在創建容器是就會加載bean。--> <!-- 初始化方法:init-method,spring創建bean的時候會執行--> <!-- 銷毀bean方法:destroy-method spring銷毀bean的時候會執行--> <bean name = "user" class="com.bing.tao.bean.User" scope="singleton" lazy-init="false" init-method="init" destroy-method="userDestroy"> <!-- property 標簽,是用於bean內部屬性初始化值使用的。--> <!-- name 對應bean的變量名,value 就是初始值。--> <property name="id" value="1"></property> <property name="name" value="蕾蕾"></property> <property name="passWord" value="123456"></property> <!-- 引用類型的初始化 --> <property name="pet" ref="pet"></property> </bean> <!-- 將pet對象交給spring管理,並注入值類型 --> <bean name = "pet" class="com.bing.tao.bean.Pet"> <property name="petType" value="二哈"></property> <property name="color" value="灰灰"></property> </bean> </beans>
運行結果:
配置文件,已經將標簽含義說明清楚。補充一點:如果是多例則spring不在管理bean而是交給你管理,銷毀方法將不再執行。
Spring XML配置如何支持構造函數和復雜數據類型(List等):
修改User類:
public class User { String id; String name; String passWord; Pet pet; public Pet getPet() { return pet; } public void setPet(Pet pet) { this.pet = pet; } public User(){ System.out.println("spring 需要一個空參構造!"); } public User(String name, Pet pet) { System.out.println("打印構造方法1:name :"+name +"pet:"+pet); this.name = name; this.pet = pet; } public User(Pet pet,String name) { System.out.println("打印構造方法2:name :"+name +"pet:"+pet); this.name = name; this.pet = pet; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassWord() { return passWord; } public void setPassWord(String passWord) { this.passWord = passWord; } @Override public String toString() { return "User{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", passWord='" + passWord + '\'' + ", pet=" + pet + '}'; } public void init(){ System.out.println("User初始化執行init方法!"); } public void userDestroy(){ System.out.println("userDestroy方法被執行!"); } }
新增測試方法:
import com.bing.tao.bean.MyCollection; import com.bing.tao.bean.User; import org.junit.jupiter.api.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; public class HelloSpring2 { @Test public void Test1(){ ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext_Injection.xml"); User user= (User) applicationContext.getBean("user"); System.out.println(user); System.out.println("-----------------分割線-----------------"); MyCollection myCollection= (MyCollection) applicationContext.getBean("myCollection"); System.out.println(myCollection); } }
新增配置文件:applicationContext_Injection.xml
配置內容如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 構造方法注入 --> <bean name="user" class="com.bing.tao.bean.User"> <!-- name 調用構造方法的參數名稱 value 是注入值類型 ref 注入引用類型 --> <!-- type 是指定參數的類型 --> <!-- index 是指定參數的 --> <constructor-arg name="name" value="老王" type="java.lang.String" index="1"/> <constructor-arg name="pet" ref="pet"/> </bean> <!-- 將pet對象交給spring管理,並注入值類型 --> <bean name = "pet" class="com.bing.tao.bean.Pet"> <property name="petType" value="二哈"></property> <property name="color" value="灰灰"></property> </bean> <!-- 復雜類型注入 --> <bean name="myCollection" class="com.bing.tao.bean.MyCollection"> <!-- Array --> <property name="array"> <array> <value>123</value> <value>abc</value> <ref bean="pet"></ref> </array> </property> <!-- List --> <property name="list"> <list> <value>456</value> <value>def</value> <ref bean="user"></ref> </list> </property> <!-- Set --> <!-- 當只有一個值得時候,可以簡寫成一下方式。 --> <property name="set" value="789"></property> <!-- Map --> <property name="map"> <map> <entry key="root" value="123"></entry> <entry key="admin" value="456"></entry> <entry key-ref="user" value-ref="pet"></entry> </map> </property> <!-- properties --> <property name="prop"> <props> <prop key="name">老李</prop> <prop key="age">25</prop> </props> </property> </bean> </beans>
運行結果:
看到這邊,大部分人都會覺得,每一個Bean都要這么操作一下,這么復雜,還不如直接寫代碼呢。
接下來,我們來簡化配置。
先來簡化配置:(新建一個配置文件:applicationContext_annotation.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" xmlns:contest="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 將包 com.bing.tao.bean 下的Bean都交給Spring --> <contest:component-scan base-package="com.bing.tao.bean"></contest:component-scan> </beans>
將User修改成:
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; /** * @Component 用於標記該bean需要Spring實例化。 * @Scope 標簽用於標記該bean是單例還是多例,singleton表示單例,prototype多例。 */ @Component("user") @Scope(scopeName = "singleton") public class User { /** * @Value標簽可以將括號中的值注入到Spring生成的Bean中 */ @Value("1") String id; @Value("蕾蕾") String name; @Value("123") String passWord; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassWord() { return passWord; } public void setPassWord(String passWord) { this.passWord = passWord; } public String toString(){ return"name: "+name+" id: "+id; } //構造后調用 @PostConstruct public void init(){ System.out.println("User初始化執行init方法!"); } //銷毀前調用 @PreDestroy public void userDestroy(){ System.out.println("userDestroy方法被執行!"); } }
創建一個測試方法:
import com.bing.tao.bean.User; import org.junit.jupiter.api.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; public class HelloSpring3 { @Test public void Test1(){ ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext_annotation.xml"); //通過getBean獲取配置好的user對象(程序員向spring容器要對象) User user= (User) applicationContext.getBean("user"); System.out.println(user); //scope="singleton" 是單例下才能出發銷毀bean方法,如果是多例則spring不在關聯bean而是交給你管理。 applicationContext.close(); } }
運行結果:
這樣就可以批量設置模式一樣的Bean結構了。XML的配置就可以很好的簡化。同時還倒逼了目錄結構的整齊。
總結來源:http://www.sikiedu.com/ 網站學習。