1、Spring是什麼?有什麼用?spring
Spring的適用環境是這樣的,假設如今有一個類port,它將提供一個返回消息的功能,代碼以下:spring-mvc
public class port { private weiboMessage weiboMessage; public port(weiboMessage weiboMessage){ this.weiboMessage = weiboMessage; } public String getMessage(){ return weiboMessage.getMessage(); } }
從getMessage方法中咱們能夠看到,返回的消息是經過weiboMessage這個對象的完成的,因此這個port類功能的實現,是須要在其內部建立這樣一個對象,在這樣的場景中port稱做被注入對象,weiboMessage稱做被依賴對象。mvc
在開發的時候一個類的實現一般須要依賴其餘對象,有時候還會出現這樣的實現方法(其實大多數時候是這樣實現的):app
public String getMessage(){ weiboMessage weiboMessage = new weiboMessage(); return weiboMessage.getMessage(); }
在使用的時候再來建立這個對象,這樣的主動的去獲取對象實際上是沒有必要的,若是依賴的對象過多的話咱們應該考慮轉變依賴對象的方式。框架
在Spring中Ioc容器實現的就是改變咱們使用依賴對象的方式,像上面那樣被注入對象會直接依賴於被依賴對象,在Ioc中,Ioc將承擔提供依賴對象的服務,全部的被注入對象和被依賴對象都將被Ioc所管理,被注入的對象須要什麼就跟Ioc要。ssh
2、注入方式ide
依賴注入的方式有三種,構造方法注入、setter方法注入和接口注入,這裏就說一下前兩種吧,由於接口注入我以爲好麻煩==測試
public class port { private weiboMessage weiboMessage; public port(weiboMessage weiboMessage){ this.weiboMessage = weiboMessage; } ...... }
這中場景下Ioc將會掃描被注入對象的構造方法,從而獲取它的依賴對象列表,從而進行對象注入。this
這種方法注入方式比較直觀,對象構造完成就處於就緒狀態,隨時均可以使用。spa
public class port { private weiboMessage weiboMessage; public void setWeiboMessage(weiboMessage weiboMessage) { this.weiboMessage = weiboMessage; } ...... }
這樣外界能夠經過調用setter方法爲被注入對象注入所依賴的對象了。這樣能夠在對象構造完成後再注入對象。
3、使用配置文件的方式實現依賴注入(xml方式)
首先建立一個表示功能的接口:
public interface port { String getMessage(); }
而後是實現該接口的兩個類(注入方式不一樣):
public class portAImpl implements port { private weiboMessage weiboMessage; public portAImpl(weiboMessage weiboMessage) { this.weiboMessage = weiboMessage; } @Override public String getMessage() { return "A: " + weiboMessage.toString(); } }
public class portBImpl implements port { private weiboMessage weiboMessage; public void setWeiboMessage(weiboMessage weiboMessage) { this.weiboMessage = weiboMessage; } @Override public String getMessage() { return "B: " + weiboMessage.toString(); } }
而後是weiboMessage這個類的實現,
public class weiboMessage { private int id; private String date; private String message; public weiboMessage(int id,String date,String message){ this.id = id; this.date = date; this.message = message; } public long getId() { return id; } public void setId(int id) { this.id = id; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } @Override public String toString() { return "id: " + id + "date: " + date + "message " + message; } }
這樣就實現了一個被依賴類weiboMessage,兩個被注入類portAImpl和portBImpl。再而後是配置文件applicationContext.xml的編寫:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd"> <bean id="portA" class="com.ssh.respository.impl.portAImpl"> <constructor-arg> <ref bean="weibomessage"/> </constructor-arg> </bean> <bean id="portB" class="com.ssh.respository.impl.portBImpl"> <property name="weiboMessage"> <ref bean="weibomessage"/> </property> </bean> <bean id="weibomessage" class="com.ssh.respository.weiboMessage"> <constructor-arg value="233"/> <constructor-arg value="2018.3.26"/> <constructor-arg value="a message"/> </bean> </beans>
<bean>....</bean>這樣的標籤就定義了一個類,Ioc中將會記錄這個對象的信息,信息包括class類型、是否爲抽象對象、構造方法參數及其餘屬性等。而後就能夠根據id向Ioc發出請求就能獲得相應的對象。
先看id爲weibomessage的中的<constructor-arg>標籤表示將使用構造方法進行注入,這裏根據構造方法中輸入參數的順序依次進行賦值,id=233,date=2018.3.26,message=a message。
id爲portA也一樣相似,不過它注入的對象是已經在Ioc容器中已經被註冊的類,因此<constructor-arg>標籤中的<ref>標籤中的bean屬性值將是已被註冊類的id
前兩個都是使用構造方法進行注入的,id爲portB的就是使用setter方法進行註冊的,使用的是<property>標籤,name的值與setter方法的名字有關,bean就是id。
這樣就算配置完成了,而後是測試類:
public class test { public static void main(String[] args){ ApplicationContext context = new ClassPathXmlApplicationContext("/META-INF/applicationContext.xml"); port A = (port)context.getBean("portA"); port B = (port)context.getBean("portB"); System.out.println(A.getMessage()); System.out.println(B.getMessage()); } }
運行結果是:
A: id: 233date: 2018.3.26message a message
B: id: 233date: 2018.3.26message a message
最後的使用分爲如下兩步:
第一步是咱們使用框架 API ClassPathXmlApplicationContext() 來建立應用程序的上下文。這個 API 加載 beans 的配置文件並最終基於所提供的 API,它處理建立並初始化全部的對象,即在配置文件中提到的 beans。
第二步是使用已建立的上下文的 getBean() 方法來得到所需的 bean。這個方法使用 bean 的 ID 返回一個最終能夠轉換爲實際對象的通用對象。一旦有了對象,你就能夠使用這個對象調用任何類的方法。
最後給一張此次的demo的項目結構吧,部署這種框架的時候也是常常在項目結構上出錯,不過並不就是說我這個項目結構就是正確的,只是能運行而已:
藍色標註的是我此次用到的,其餘的是多餘的不必在乎。