1. 程式人生 > >Spring框架自學之路(三)

Spring框架自學之路(三)

(03Day)

        (1)Bean的自動裝配

            在前面的例子中我們為Bean裝配Bean很明顯都是手動裝配的,那麼既然有手動裝配那有沒有自動裝配呢?顯然是有的。那麼自動裝配又該如何使用呢?其實很簡單,來看看吧。

            為Bean設定自動裝配只需要在Bean中設定autowire並指定自動裝配的模式就行了。

            atuowire有三種裝配模式分別是:

  1. byType:根據型別進行自動裝配,若IOC容器中有多個目標與目標Bean型別一致,這種情況下會丟擲異常。
  2. byName:根據名稱完成自動裝配:必須將目標Bean的屬性名和名稱設定的完全相同,IOC會根據Get方法獲取。
  3. constructor:通過構造方法進行自動裝配,當Bean中存在多個構造方法的時候,這種配置方法會很複雜,因此不推薦使用。

            在spring中的配置檔案如下:

<?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:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id = "address" class="com.autowire.Address" p:city="廈門" p:street="集美"></bean>
<bean id = "car" class="com.autowire.Car" p:brand="奧迪" p:price="300000"></bean>
<!-- 手動裝配 
<bean id = "person" class="com.autowire.Person" p:name="李四" p:car-ref="car" p:address-ref="address"></bean>
-->
<!-- 使用autowire自動裝配,屬性指定自動裝配的方式
	 byNmae是根據該Bean的名字和當前 Bean的setter方法除去set後的方法名進行自動裝配,若沒有匹配的方法,則不裝配
	 byType是根據該Bean的型別和當前Bean的屬性的型別進行自動裝配。注意:若IOC容器中有一個以上的該型別匹配的bean,則丟擲異常。
 -->
<bean id = "person" class="com.autowire.Person" p:name="李四" autowire="byName"></bean>
</beans>

             測試類

package com.autowire;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main4 {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans-autowire.xml");
		Person person = (Person) ctx.getBean("person");
		System.out.println(person);
	}

}

        1.一旦使用自動裝配,那麼該Bean所有的引用屬性都必須使用自動裝配,不能有的使用自動裝配,有的使用手動裝配。

        2.要麼根據型別自動裝配,要麼根據屬性名自動裝配,不能兩者同時使用。

        3.一般情況下,在實際的專案中很少使用自動裝配功能,因為和自動裝配功能所帶來的好處比起來,明確清晰的配置文件更有說服力一些。

    (2)Bean之間的關係

                2-1 繼承

                    說到繼承,也許會想到我們java中面向物件的繼承,但是在這繼承並不是指java中面向物件的父類子類繼承,而是

                    指配置上的繼承。在spring中Bean的繼承其實很簡單,主要就是在Bean的元素中新增parent = “繼承的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"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	<!-- 不使用繼承的方式 
		<bean id = "address1" class="com.autowire.Address"
		 p:city="廈門" p:street="集美區"></bean>
		<bean id = "address2" class="com.autowire.Address"
		p:city="廈門" p:street="海滄區"></bean>
	-->
	<!-- 使用繼承的方式 parent 代表要繼承的Bean 同時也可以繼承模版,模版就是Bean 加上abstract = “true” -->
		<bean id = "address1" class="com.autowire.Address"
		 p:city="廈門" p:street="集美區"></bean>
		 <!-- 繼承address1 Bean -->
		<bean id = "address2" parent="address1"
		p:street="海滄區"></bean>
		<!-- 定義一個模版,模版上可以不寫class路徑,也可以寫,同時abstract為true的bean是不會被
			 IOC容器初化的,只能用來被繼承配置。同理若一個Bean的Class沒有指定,則該Bean必須是一個
			 抽象Bean。
		 -->
		<bean id = "address" p:city="廈門"  p:street="集美區" abstract="true"></bean>
		<!-- 繼承模版 並不是所有的元素的都會被繼承 例如 abstract就不會被繼承 -->
		<bean id = "address3" class="com.autowire.Address" parent="address"
		p:street="思明區"></bean>
</beans>

                   2-2 依賴

                        那麼何為依賴呢,通俗來說就是Bean1依賴於Bean2,那麼Bean1建立的時候在IOC容器中必須要存在Bean2。

                        廢話不多說,具體細節用程式碼來說明。

<?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:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	<!-- 不實用繼承的方式 
		<bean id = "address1" class="com.autowire.Address"
		 p:city="廈門" p:street="集美區"></bean>
		<bean id = "address2" class="com.autowire.Address"
		p:city="廈門" p:street="海滄區"></bean>
	-->
	<!-- 使用繼承的方式 parent 代表要繼承的Bean 同時也可以繼承模版,模版就是Bean 加上abstract = “true” -->
		<bean id = "address1" class="com.autowire.Address"
		 p:city="廈門" p:street="集美區"></bean>
		 <!-- 繼承address1 Bean -->
		<bean id = "address2" parent="address1"
		p:street="海滄區"></bean>
		<!-- 定義一個模版,模版上可以不寫class路徑,也可以寫,同時abstract為true的bean是不會被
			 IOC容器初化的,只能用來被繼承配置。同理若一個Bean的Class沒有指定,則該Bean必須是一個
			 抽象Bean。
		 -->
		<bean id = "address" p:city="廈門"  p:street="集美區" abstract="true"></bean>
		<!-- 繼承模版 並不是所有的元素的都會被繼承 例如 abstract就不會被繼承 -->
		<bean id = "address3" class="com.autowire.Address" parent="address"
		p:street="思明區"></bean>
		
		<!-- 依賴Bean的配置 此時若是car沒在IOC容器中定義,那麼執行程式的時候會丟擲異常
			 所以說依賴Bean就是配置Person的時候,必須有一個car與之關聯,也就是說person這個
			 Bean依賴與Car這個Bean。依賴就是為了讓建立person這個Bean之前IOC容器中必須存
			 在Car這個Bean,如果需要依賴多個Bean可以通過逗號或者空格的方式配置。
		 -->
		 <bean id = "car" class="com.autowire.Car" 
		 p:brand="賓士" p:price="5000000"></bean>
		<bean id = "person" class="com.autowire.Person" 
		p:name="Garon" p:address-ref="address3" depends-on="car"></bean>
</beans>   

              測試類

package com.relation;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.autowire.Address;
import com.autowire.Person;

public class Main5 {

	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-relation.xml");
		Address address = (Address) ctx.getBean("address1");
		System.out.println(address);
		address = (Address) ctx.getBean("address2");
		System.out.println(address);
		address = (Address) ctx.getBean("address3");
		System.out.println(address);
		Person person = (Person) ctx.getBean("person");
		System.out.println(person);
	}

}

    (3)Bean的作用域

            預設情況下在IOC容器下配置的Bean是單例模式的,也就是說IOC容器只會為這個Bean節點建立一個例項物件,每次呼叫GetBean方法都會返回同一個Bean。

            那麼如果配置Bean 的作用域呢?只需要在Bean的屬性中配置 scope元素就行了,scope元素有以下4個元素:

                 1)singleton:單利的,預設值,容器在初始化的時候建立bean例項,整個容器的生命週期只建立這一個Bean。
 2)prototype:原型的,容器在初始化的時候不建立Bean,在每一次請求的時候都會建立一個新的例項並返回。
 3)request:每次http請求將會有各自的bean例項,類似於prototype。

 4)session:在一個http session中,一個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"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	<!-- 使用Bean的scope屬性來配置bean的作用域
		 singleton:單利的,預設值,容器在初始化的時候建立bean例項,整個容器的生命週期只建立這一個Bean。
		 prototype:原型的,容器在初始化的時候不建立Bean,在每一次請求的時候都會建立一個新的例項並返回。
		 request:每次http請求將會有各自的bean例項,類似於prototype。
		 session:在一個http session中,一個bean定義對應一個bean例項。
	 -->
	<bean id= "car1" class="com.autowire.Car"
	p:brand="寶馬" p:price="350000" scope="prototype"></bean>
	
</beans>

        測試類

package com.scope;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.autowire.Car;

public class Main6 {

	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-scope.xml");
		Car car1 = (Car) ctx.getBean("car1");
		Car car2 = (Car) ctx.getBean("car1");
		System.out.println(car1 == car2);
	}

}

    (4)使用外部屬性檔案

            在實際開發中我們的spring配置檔案會非常的複雜,那麼如果我們需要修改系統部署的細節資訊,是不是要在spring配置檔案中找到對應的檔案進行修改呢?很明顯這樣做非常的麻煩而且容易出錯,於是spring引入了外部屬性檔案這種配置方法使得這些部署的細節和Bean配置相分離。

            那麼如何做呢?需要在src目錄下建立一個字尾為properties的檔案,並在裡面配置好資訊後,只需要在spring的配置檔案中匯入context:properties這個名稱空間使用<context:properties-placeholder location=“classpath:外部檔案的名字”>就可以了。這樣在Bean的配置檔案就可以使用類似於EL表示式的方式${var}取值.

            外部屬性檔案類似於這樣寫

這樣如果要取user這個值只需要再對應的value中使用${user}就可以取到root這個值,以後需要修改基礎的配置資訊,只需要到外部屬性檔案裡修改就行了,這樣是不是更方便且不容易出錯。