IoC 簡介
平常的Java開發中,程式設計師在某個類別中需要依賴其它類別的方法。
通常是new一個依賴類別再呼叫類別實例的方法,這種開發存在的問題是new的類別實例不好統一管理。
Spring提出了依賴注入的思想,即依賴類別不由程式設計師實例化,而是透過Spring容器幫我們new指定實例並且將實例注入到需要該物件的類別中。
依賴注入的另一種說法是"控制反轉"。通俗的理解是:平常我們new一個實例,這個實例的控制權是我們程式設計師。
而控制反轉是指new實例工作不是由我們程式設計師來做而是交給Spring容器來做。
Spring有多種依賴注入的形式,本篇文章僅介紹Spring透過xml進行IOC配置的方式。
1.Set注入
這是最簡單的注入方式,假設有一個SpringAction,類別中需要實例化一個SpringDao對象,那麼就可以定義一個private的SpringDao成員變量,然後創建SpringDao的set方法(這是ioc的注入入口):
隨後編寫spring的xml文件,
<!--配置bean,配置后该类由spring管理--> <bean name="springAction" class="com.bless.springdemo.action.SpringAction"> <!--(1)依赖注入,配置当前类中相应的属性--> <property name="springDao" ref="springDao"></property> </bean> <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>
2.建構器注入
這種方式的注入是指帶有參數的建構函式註入,看下面的例子,我建立了兩個成員變數SpringDao和User,但是並未設定物件的set方法,所以就不能支援第一種注入方式,這裡的注入方式是在SpringAction的建構子中注入,也就是說在創建SpringAction物件時要將SpringDao和User兩個參數值傳進來:
#public class SpringAction { //注入对象springDao private SpringDao springDao; private User user; public SpringAction(SpringDao springDao,User user){ this.springDao = springDao; this.user = user; System.out.println("构造方法调用springDao和user"); } public void save(){ user.setName("卡卡"); springDao.save(user); } }
在XML檔案中同樣不用
##
<!--配置bean,配置后该类由spring管理--> <bean name="springAction" class="com.bless.springdemo.action.SpringAction"> <!--(2)创建构造器注入,如果主类有带参的构造方法则需添加此配置--> <constructor-arg ref="springDao"></constructor-arg> <constructor-arg ref="user"></constructor-arg> </bean> <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean> <bean name="user" class="com.bless.springdemo.vo.User"></bean>
##下面是設定index,就是參數位置:
<bean name="springAction" class="com.bless.springdemo.action.SpringAction"> <constructor-arg index="0" ref="springDao"></constructor-arg> <constructor-arg index="1" ref="user"></constructor-arg> </bean>
另一個是設定參數類型:
##
<constructor-arg type="java.lang.String" ref=""/>
3.靜態工廠的方法注入
靜態工廠顧名思義,就是透過呼叫靜態工廠的方法來取得自己需要的對象,為了讓spring管理所有對象,我們不能直接透過"工程類.靜態方法()"來取得對象,而是依然透過spring注入的形式取得:
#
package com.bless.springdemo.factory; import com.bless.springdemo.dao.FactoryDao; import com.bless.springdemo.dao.impl.FactoryDaoImpl; import com.bless.springdemo.dao.impl.StaticFacotryDaoImpl; public class DaoFactory { //静态工厂 public static final FactoryDao getStaticFactoryDaoImpl(){ return new StaticFacotryDaoImpl(); } }
##同樣看關鍵類,這裡我需要注入一個FactoryDao對象,這裡看起來跟第一種注入一模一樣,但是看隨後的xml會發現有很大差別:
public class SpringAction { //注入对象 private FactoryDao staticFactoryDao; public void staticFactoryOk(){ staticFactoryDao.saveFactory(); } //注入对象的set方法 public void setStaticFactoryDao(FactoryDao staticFactoryDao) { this.staticFactoryDao = staticFactoryDao; } }
Spring的IOC配置文件,注意看
<!--配置bean,配置后该类由spring管理--> <bean name="springAction" class="com.bless.springdemo.action.SpringAction" > <!--(3)使用静态工厂的方法注入对象,对应下面的配置文件(3)--> <property name="staticFactoryDao" ref="staticFactoryDao"></property> </property> </bean> <!--(3)此处获取对象的方式是从工厂类中获取静态方法--> <bean name="staticFactoryDao" class="com.bless.springdemo.factory.DaoFactory" factory-method="getStaticFactoryDaoImpl"></bean>
實例工廠的意思是取得物件實例的方法不是靜態的,所以你需要先new工廠類,再呼叫普通的實例方法:
public class DaoFactory { //实例工厂 public FactoryDao getFactoryDaoImpl(){ return new FactoryDaoImpl(); } }
那麼下面這個類沒什麼說的,跟前面也很相似,但是我們需要透過實例工廠類別建立FactoryDao物件:
public class SpringAction { //注入对象 private FactoryDao factoryDao; public void factoryOk(){ factoryDao.saveFactory(); } public void setFactoryDao(FactoryDao factoryDao) { this.factoryDao = factoryDao; } }
#最後看spring設定檔:
<!--配置bean,配置后该类由spring管理--> <bean name="springAction" class="com.bless.springdemo.action.SpringAction"> <!--(4)使用实例工厂的方法注入对象,对应下面的配置文件(4)--> <property name="factoryDao" ref="factoryDao"></property> </bean> <!--(4)此处获取对象的方式是从工厂类中获取实例方法--> <bean name="daoFactory" class="com.bless.springdemo.factory.DaoFactory"></bean> <bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean>
5.總結
<bean name="..." class="..." scope="prototype">