spring4之依賴注入的三種方式


1、Setter注入

        <bean id="helloWorld" class="com.jdw.spring.beans.HelloWorld">
		<property name="name" value="Spring"></property>
	</bean>

  從這個最簡單的配置可以得出以下兩個結論:一、class屬性需要全類名進行配置,說了ioc容器是通過反射進行創建bean的;二、bean類必須有默認的構造函數

  這種通過property子元素進行屬性配置的方式是spring依賴注入的三大方式之一:setter注入。

2、構造器注入

         <bean id="car" class="com.jdw.spring.beans.Car">
		<constructor-arg value="audi" type="java.lang.String"></constructor-arg>
		<constructor-arg type="java.lang.String">
			<!-- 對於包含特殊字符的屬性值,可以在value子節點使用CDATA -->
			<value><![CDATA[<shanghai>]]></value>
		</constructor-arg>
		<constructor-arg type="int">
			<value>240</value>
		</constructor-arg>
	</bean>

  構造器注入,言外之意,需要在bean之中配置構造器,可以不需要默認構造方法,但是必須保證構造器參數與配置文件中的參數數量和類型一致

	<bean id="car1" class="com.jdw.spring.beans.Car">
		<constructor-arg value="audi" index="0" type="java.lang.String"></constructor-arg>
		<constructor-arg value="shanghai" index="1" type="java.lang.String"></constructor-arg>
		<constructor-arg value="200000" index="2" type="double"></constructor-arg>
	</bean>

  對於有多個構造器的bean,可通過上述的index和type屬性進行配置,以區別重載的構造器

3、工廠方法注入

    工廠方法注入又分為靜態工廠方法注入和實例工廠方法注入

    (1)靜態工廠方法注入

    一個模擬的簡單靜態工廠如下,該靜態工廠提供了一個靜態方法getCar,調用該方法則返回一個Car實例,注意紅色注釋,如果配置文件中scope=singleton,采用靜態工廠方法注入獲得的bean是否為單例呢?

public class StaticCarFactory {

	public static Map<String,Car> cars=new HashMap<>();
	static{
		cars.put("audi", new Car("audi",300000));
		cars.put("bmw", new Car("bmw",200000));
		cars.put("hongqi", new Car("hongqi",600000));
	}
	public static Car getCar(String name){
		//return new Car("audi",300000);//如果這么寫,那么獲得的car實例還是單例的么?
		return cars.get(name);
	}
}

  靜態工廠注入配置:

        <bean id="car" class="com.jdw.spring.factory.StaticCarFactory"
		factory-method="getCar">
		<constructor-arg value="audi"></constructor-arg>
	</bean>

    說明:所謂靜態工廠方法注入,不過是通過一個靜態方法創建bean的實例,注意,在singelton情況下該靜態方法只會在ioc容器初始化bean時調用一次,即不管getBean("car")多少次,都是返回的同一個Car對象。而在prototype情況下,getBean("car")調用一次就會對應的調用一次靜態方法getCar。從這里可以更好的理解singleton和prototype的區別,前者會在ioc容器初始化時創建,后者則在用戶調用時再創建。

    (2)實例工廠方法注入

  實例工廠代碼:

public class InstanceCarFactory {
	private Map<String, Car> cars = null;

	public InstanceCarFactory() {
		cars = new HashMap<>();
		cars.put("audi", new Car("audi", 30000));
		cars.put("BMW", new Car("audi", 20000));
		cars.put("HQ", new Car("audi", 50000));
	}

	public Car getCar(String brand) {
		return cars.get(brand);
	}
}

  實例工廠的getCar為非靜態,這就導致,必須先實例化該工廠,即需要配置該工廠的bean。

        <!-- 配置實例工廠 -->
	<bean id="carFactory" class="com.jdw.spring.factory.InstanceCarFactory"></bean>

	<!-- 通過實例工廠配置bean -->
	<bean id="car1" factory-bean="carFactory" factory-method="getCar">
		<constructor-arg name="brand" value="audi"></constructor-arg>
	</bean>

  學而不思則罔,通過Setter注入和構造器注入可以很方便快捷的配置bean,靜態工廠注入和實例工廠注入到底是為了那樣?難道只是為了支持下工廠模式?spring你別逗好么,咱自己不就相當於一個超級bean工廠么!那干嘛還弄給工廠方法注入呢?一定有其原因。

      有一家手機賣場,只賣A、B、C三種手機,假設顧客只關心價格price和參數信息info,那么問題來了,一個顧客進入賣場,說:我要買A手機。手機賣場(IOC)需要初始化一個A的Bean。又一個顧客進入賣場,說:我要B手機。手機賣場也得初始化一個B的bean。同樣,也得初始化C的bean。三個手機還好些,IOC就建立三個bean,那么10種手機呢?每種手機的info需要特殊處理呢?比如手機參數信息要有一系列的運算統計信息呢?這樣看來IOC貌似不適合把每個bean都放在配置文件里,也不適合建立多個bean。

  解決方案就是,建立一個手機bean,通過工廠注入(靜態工廠、實例工廠都可以),傳入手機類型名稱,獲得對應的手機,只是要把bean配置為prototype,這樣運行時就可以獲取各式各樣的手機了!

     那靜態工廠和實例工廠兩種注入方式,除了配置的不同,在應用上有什么區別么?

  

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM