本來這篇文章差不多有一萬七百字左右,從IOC到AOP,算是對自己學習Spring的一個驗收,同時也分享出來供大家查漏補缺,但因為內容實在太多,所以就先碼了IOC的這篇內容,明天再補發AOP的內容,希望大家多多支持,
同時提供免費的學習資料,學習技術內容包含有:Spring,Dubbo,MyBatis, RPC,原始碼分析,高并發、高性能、分布式,性能優化,微服務 高級架構開發等等,
需要的朋友可以點擊:點這個!點這個!,暗號:csdn,

IoC 思想
IOC(控制反轉)是一種依賴倒置原則的代碼設計的思路,它主要采用(DI)依賴注入的方式來實作,
不使用IoC思想的傳統模式
在傳統模式中,物件由程式員主動創建,控制權在程式員手中,
程式可以做到正常作業,但仍有一個難以避免的問題,
如果用戶需求變更,程式員就要修改對應的代碼,代碼量不大還好,如果代碼量巨大的話 修改一次的成本…
這個問題就是耦合性過高引起的,修改一次需求,或多或少會造成代碼的修改,作業量先不說,維護起來也是極其不便的啊,

- 就如上圖中這四個齒輪(物件)一樣,互相嚙合,如果有一方停止或更換 其他的齒輪也就沒辦法作業,這自然不是我們希望看到的,
為了解決物件間耦合過高的問題,軟體專家Michael Mattson提出了IoC理論,用來實作物件之間的“解耦”,
那么應當如何去達到理想的效果呢?
使用IoC思想后的模式
IoC的主要思想是借助一個“第三方”來拆開原本耦合的物件,并將這些物件都與“第三方”建立聯系,由第三方來創建、操作 這些物件,進而達到解耦的目的,

因此IoC容器也就成了整個程式的核心,物件之間沒有了聯系(但都和IoC容器有聯系),
這里參考一句知乎上看到的話
IoC的思想最核心的地方在于,資源不由使用資源的雙方管理,而由不使用資源的第三方管理,這可以帶來很多好處,第一,資源集中管理,實作資源的可配置和易管理,第二,降低了使用資源雙方的依賴程度,也就是我們說的耦合度,
什么是控制反轉
這里我們引入一個場景, 如果A物件想呼叫B物件,
傳統模式中該如何操作 大家都很熟悉了,在A物件中創建一個B物件實體,就可以滿足A物件呼叫B物件的需求,這是我們在A物件中主動的去創建B物件.
而引入IoC后,A物件如果想呼叫B物件,IoC容器會創建一個B物件注入到A物件中,這樣也可以滿足A物件的呼叫需求,但是程序由我們的主動創建,變成了A物件被動的去接收IoC容器注入的B物件,
A物件依賴B物件的程序,由程式員的主動創建B物件供其依賴,變為了被動的接收IoC容器注入的物件,控制權從程式員手中交到了IoC容器手中,A物件獲得依賴的程序也由主動變為被動,這就是所謂的控制反轉,
什么是依賴注入(DI)
依賴注入是IoC思想最主要的實作方式,也就是上文提到的A物件如果想呼叫B物件,IoC容器會創建一個B物件注入到A物件中,這樣就可以滿足A物件對B物件的依賴需求,這個行為就是依賴注入,
DI ≠ IOC
IoC的概念更寬廣一些,而DI是IoC的主要實作方式,但這并不意味著DI就是IoC,將二者混為一談 這是不對的,很容易誤導他人,
就比如你想要閱讀,最主要的實作方式自然是“用眼睛長時間的去看”,但你不能把這個“眼睛長時間去看”的行為 理解為閱讀,(可能例子有點不恰當)
注入方式
setter方法注入
我們需要在類中生成一個set方法和一個空構造(空構造在沒有宣告有參構造時會隱式宣告,無需再進行多余的操作)
public class Hello {
private String name;
// 一定要生成set方法
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
在Spring組態檔中注入Bean(物件),在Bean中使用property標簽為name屬性賦值
寫一個簡單的測驗方法,測驗property標簽是否成功賦值(是),
構造器注入
構造器注入我們需要手動的生成一個有參構造
package com.molu.pojo;
public class Hello {
private String name;
// 生成有參構造
public Hello(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
這個時候再切回applicationContext.xml中可以看到已經報錯了

因為顯式的定義了有參構造后,無參構造就不存在了,我們需要將property標簽改為constructor-arg
constructor-arg標簽賦值的方式更為多樣化,
- 通過下標賦值
<bean id="hello" class="com.molu.pojo.Hello">
<constructor-arg index="0" value="陌路"/>
</bean>
- 通過引數型別賦值(不推薦,引數型別容易重合)
<bean id="hello" class="com.molu.pojo.Hello">
<constructor-arg type="java.lang.String" value="陌路"/>
</bean>
- 通過引數名賦值(推薦)
<bean id="hello" class="com.molu.pojo.Hello">
<constructor-arg name="name" value="陌路"/>
</bean>
結果都是一樣的,這里就不再展示測驗結果了
拓展注入
P(Property)命名空間注入
- 在使用P命名空間之前要在引入它的約束
xmlns:p="http://www.springframework.org/schema/p"
- P命名空間的使用必須要有一個空構造,(類似于setter方法注入)但前面也說了,沒有宣告有參構造時 空構造會隱式宣告,
- P命名空間注入 可以直接在Bean標簽中進行注入
首先創建一個Me類
package com.molu.pojo;
public class Me {
private String name;
private int age;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
在applicationContext.xml中用P命名空間進行注入
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--在Bean標簽中,使用P命名空間進行簡單的屬性注入-->
<bean id="me" class="com.molu.pojo.Me" p:name="陌路" p:age="18"/>
</beans>
測驗
略…
C(constructor-arg)命名標簽注入
- 使用C命名空間之前也需要引入約束
- xmlns:c=“http://www.springframework.org/schema/c”
- C命名空間不同于P命名空間,他必須要有一個構造方法(類似構造器注入)
- P命名空間也可以直接在Bean標簽中進行簡單的注入操作
在Me類中添加構造器
package com.molu.pojo;
public class Me {
private String name;
private int age;
// 生成有參構造 供C命名空間呼叫
public Me(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
在applicationContext.xml中用C命名空間進行注入
<!--C命名空間注入,通過構造器注入-->
<bean id="me" class="com.molu.pojo.Me" c:name="陌路" c:age="18" />
測驗
略…
關于其他的注入方式這里就不再一一列舉了,官網上寫的很詳細,有能力的朋友可以移步官網,在官網上尋求答案
補充
我們再寫一個HelloTwo類,里面和Hello類一樣,唯一不同是顯式的定義了無參構造而不是有參構造,
package com.molu.pojo;
public class HelloTwo {
private String name;
// 顯式的定義了無參構造
public HelloTwo() {
// 簡單寫一個測驗輸出陳述句
System.out.println("HelloTwo的無參構造被呼叫了");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
在Application Context.xml中注冊bean,不對其進行其他任何操作,
<bean id="helloTwo" class="com.molu.pojo.HelloTwo"></bean>
使用剛剛用過的Hello類測驗方法 原封不動進行測驗
public class MyTest {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Hello hello = (Hello) context.getBean("hello");
System.out.println(hello.getName());
}
}
控制臺輸出了我們在HelloTwo無參構造中寫的輸出陳述句,奇怪的是我們并沒有在測驗類中寫任何關于HelloTwo的代碼,,

由此能夠得到一些資訊:“注冊進applicationContext.xml中的bean,無論你呼叫與否,他都會被初始化”
ioc到這里就總結得差不多了,下一篇文章就講講AOP,
最后還有Java核心知識點+全套架構師學習資料和視頻+一線大廠面試寶典+面試簡歷模板可以領取+阿里美團網易騰訊小米愛奇藝快手嗶哩嗶哩面試題+Spring原始碼合集+Java架構實戰電子書+2020年最新大廠面試題,
需要的朋友可以點擊:點這個!點這個!,暗號:csdn,


轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/204117.html
標籤:java
上一篇:淚目,復習了兩個月終于拿到offer,Java集合+Spring+并發+Redis+JVM調優面試題干貨整理
下一篇:cgb2007-京淘day06
