了解依賴注入
前言
先了解下控制反轉--轉自知乎的國哥
如果一個類A 的功能實現需要借助於類B,那么就稱類B是類A的依賴,如果在類A的內部去實例化類B,那么兩者之間會出現較高的耦合,一旦類B出現了問題,類A也需要進行改造,如果這樣的情況較多,每個類之間都有很多依賴,那么就會出現牽一發而動全身的情況,程序會極難維護,並且很容易出現問題。要解決這個問題,就要把A類對B類的控制權抽離出來,交給一個第三方去做,把控制權反轉給第三方,就稱作控制反轉(IOC Inversion Of Control)。控制反轉是一種思想,是能夠解決問題的一種可能的結果,而依賴注入(Dependency Injection)就是其最典型的實現方法。由第三方(我們稱作IOC容器)來控制依賴,把他通過構造函數、屬性或者工廠模式等方法,注入到類A內,這樣就極大程度的對類A和類B進行了解耦。
想理解控制反轉,就得想清楚這個第三方,在spring中便是IOC容器。將原本兩個耦合性很強的對象分給中介第三方進行控制。
依賴注入是實現控制反轉的一種方式,依賴注入是將實例變量傳入到一個對象中去的過程、方式、一種設計模式。依賴注入方式下,注入將依賴傳給調用方,不是像原來的調用方直接使用依賴。所以很明顯也是為了解耦,參考下wiki的圖,了解大概分類


上面的官網中講到依賴注入是依靠這兩個主要的方式依賴-基於構造器的依賴注入和基於setter的依賴注入。下面就講下詳細的實現方式。
實現依賴注入
1、構造器注入
在上一篇的spring入門篇提了,特別是三種方式,這里再記錄一下
環境
先總體的項目小測配置以及定義的各個類

實體類
package com.yhy.pojo;
public class Hello {
private String str;
public Hello(String str) {
this.str = str;
}
/**
* @return String return the str
*/
public String getStr() {
return str;
}
/**
* @param str the str to set
*/
public void setStr(String str) {
this.str = str;
}
public void show() {
System.out.println(str);
}
}
測試類
@Test
public void test()
{
//獲得spring的上下文內容
//拿到容器
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//使用容器獲得對象
Hello hello = (Hello) context.getBean("hello");
hello.show();
}
使用有參構造有幾個方法
在beans.xml中使用三種方式
- 使用參數名
<bean id="hello" class="com.yhy.pojo.Hello">
<constructor-arg name="str" value="yhy"/>
</bean>
- 使用下標索引
<bean id="hello" class="com.yhy.pojo.Hello">
<!-- 從零開始的索引值,多個參數的時候再使用別的參數 -->
<constructor-arg index="0" value="hello world"/>
</bean>

- 使用參數的類型來配置
<bean id="hello" class="com.yhy.pojo.Hello">
<constructor-arg type="java.lang.String" value="hello spring"/>
</bean>

其他
在.xml配置文件中還有兩個選項。

2、set方法注入
這個方式強調bean類要有set方法,在實例化后調用set方法完成注入。

定義一個person類來測試下set方法注入
注入的類型不同使用的不同參數在配置bean中。如下圖,可以有多個選擇在propety中,一些標簽都是可以直接秒懂的。

- 常量注入

- bean注入
<!-- bean注入 ref進行引入-->
<property name="address" ref="addr"></property>
- 數組注入
<!-- 數組注入 -->
<property name="books">
<array>
<value>悲慘世界</value>
<value>水滸傳</value>
<value>金瓶X</value>
</array>
</property>
- 列表注入
<!-- list注入 -->
<property name="hobbies">
<list>
<value>打籃球</value>
<value>健身</value>
<value>游泳</value>
</list>
</property>
- map注入
<!-- map注入 -->
<property name="card">
<map>
<entry key="銀行卡" value="82937472389"></entry>
<entry key="身份證" value="2345382937472389"></entry>
</map>
</property>
- properties注入
<!-- properties注入 -->
<property name="info">
<props>
<prop key="id">201705239</prop>
<prop key="url">yhytj.top</prop>
<prop key="name">yhy</prop>
</props>
</property>
最后的測試類
public void test() {
// 獲得spring的上下文內容
// 拿到容器
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// 使用容器獲得對象
Person person = (Person) context.getBean("person");
//這里定義了一個show方法,輸出格式,vscode自動生成tostring還不熟。使用插件生成這個
person.show();
}

- 最后輸出

拓展命名空間
在官網上還可以使用p命名空間和c命名空間簡化工作,但其實有idea開發等工具,有時也差不多了,大家可以多多了解下,我只是用了個小測試來了解。



還有一個c命名空間,對應着constructor-arg,這里就不走小demo,可以上官網了解一些
