目錄
- 二丶Spring核心和設(shè)計思想
- Spring是什么?如何理解SpringIoC和DI是什么?區(qū)別?
- 通過容器對象.getBean()獲取依賴注入:把一個Bean對象,注入到另一個Bean的屬性當(dāng)中byName:通過Bean的id/名稱來匹配如果此時你的id/名稱不存在或者說不唯一。怎么綁定?方式一:使用 @Qualifier(“XXX”)方式二: 使用@Resource(name=”XXX”)說一下@Autowired 和 @Resource 的區(qū)別
這一部分就是關(guān)于Spring的部分了,在這里我們主要學(xué)習(xí)四個部分
1、Spring2、Spring Boot3、Spring NVC4、MyBatis
這里特別對最后一個說一下,MyBatus。它是用來 代替 JDBC 編程,JDBC 作為Java 提供的一組 用來 操作數(shù)據(jù)庫 的 API非常繁瑣
1、獲取數(shù)據(jù)源2、與數(shù)據(jù)建立連接3、編寫 SQL 語句。4、執(zhí)行SQL5、此時 SQL 已經(jīng)執(zhí)行完畢,然后需要我們?nèi)メ尫刨Y源
所以重復(fù)的代碼就很多,所以不推薦使用。這里我們一步一步來
一丶為什么學(xué)框架
框架的便捷性
什么意思呢?
1、 需配置 Tomcat,點擊“運 ”按鈕就可以運 項 ,Spring Boot 內(nèi)置了 Web 容器(可直接運 )。2、 快速添加外部 jar 包(依賴)。3、 快速發(fā)布項 (使 java -jar 式就可以發(fā)布)。4、 對象 動裝配。5、 …
和servlet進(jìn)行對比
我們傳統(tǒng)的servlet怎么使用的呢?
1、創(chuàng)建一個 maven 項目2、在 pom.xml 中 引入相關(guān)依賴3、創(chuàng)建特定的目錄4、編寫代碼5、打包6、部署7、驗證程序8、發(fā)布【使用 (Tomcat) 進(jìn)行 程序的部署和發(fā)布】
光是這一連串的流程下來,就讓人絕望,我們可以清楚的發(fā)現(xiàn)servlet有以下不足
1、添加外部 jar 不 便,容易出錯, 如添加了 個不匹配的外部 jar 版本;
2、運 和調(diào)試的時候需要配置 tomcat 不 便;
3、 發(fā)布不 便,servlet 項 必須依靠外置的 tomcat(外置的 web 容器)運 。
4、 路由配置不 便, 個訪問地址對應(yīng) 個 Servlet 類。
5、…
而以上痛點問題,都可以通過 JavaEE 進(jìn)階框架解決,接下來我們一起來看。
二丶Spring核心和設(shè)計思想
Spring是什么?如何理解Spring
先從第一個問題開始,啥是Spring?
Spring 指的是 Spring Framework(Spring 框架),它是 個開源框架,有著活躍 龐 的社區(qū),這就是它之所以能 久不衰的原因。Spring 持 泛的應(yīng) 場景,它可以讓 Java 企業(yè)級的應(yīng) 程序開發(fā)起來更簡單。
所以總結(jié)一下: Spring就是包含了眾多工具方法的loC容器
這里可能就有鐵子會發(fā)問啥是容器?
容器是用容納某種物品的(基本)裝置。
是不是有點迷,那就想想我們的數(shù)據(jù)結(jié)構(gòu),List,Map。如果還是想不出來,那就再想想我們的Tomcat
List/Map -> 數(shù)據(jù)存儲容器
Tomcat -> Web 容器
這里是不是好奇為啥Tomcat是一個容器呢?
但是 Tomcat 為什么是一個 Web 容器呢?
思考一下:
Tomcat 是用來運行 外部的項目,因此它是一個 Web 容器。
你有一個項目,想要運行。
肯定是要將項目部署到 Tomcat 的 webapps 目錄底下,才可以運行。
此時,webapps 就是一個項目的容器
而 webapps 目錄,就是 Tomcat 下面的一個子目錄。
那么,我們將 Tomcat 稱為是一個容器,沒有任何問題
IoC和DI是什么?區(qū)別?
IoC = Inversion of Control 翻譯成中文是“控制反轉(zhuǎn)”的意思,也就是說 Spring 是一個“控制反轉(zhuǎn)”的容器,怎么理解這句話呢?
分成兩點,第一個點是控制,第二個點是反轉(zhuǎn)。
也就是說:之前程序的控制權(quán)限是在我們自己手上,現(xiàn)在,我們把這個控制權(quán)交出去了。
那么通過一個實際的情況來說一下
我們在 A 類 中,想去調(diào)用 B 類中的方法,是怎么做的?
是不是 要去new B 類對象,通過 對象 去調(diào)用 B類中的方法。當(dāng)前 B 的控制權(quán),是我們手上的。而 控制反轉(zhuǎn),就是將我們手上的權(quán)限,交由 “其他人” 來操作這個類。這個“其他人”,就是 Spring 框架。
此時,我們想要 A 類中調(diào)用 B 的時候, 告訴 框架,我要在 A 中 調(diào)用 B 了。
至于 B 的生命周期,和我們沒有任何關(guān)系。
這是控制反轉(zhuǎn)。
前面也說了:spring是一個控制反轉(zhuǎn)容器
也就是 像之前在傳統(tǒng)開發(fā)的時候,所有需要我們自己去new東西,都不需要我們再去new 了。因為我們把控制權(quán) “反轉(zhuǎn)給了” Spring 框架。Spring 會幫我們管理所有的對象(Bean)。
哪一個例子來舉例吧
比如說我們構(gòu)造一個car類,然后我們肯定是要new一個car對象,在car對象進(jìn)行初始化的時候是不是要new一個Framework對象?那么繼續(xù)往下走,每一次的初始化都帶著底層的對象的new,那么問題就來了,這對應(yīng)著什么呢?
如果輪胎的尺寸的固定的,然而隨著對的車的需求量越來越大,個性化需求也會越來越多,這時候我們就需要加工多種尺寸的輪胎,那這個時候就要對上面的程序進(jìn)行修改了。這一修改,就是全部的修改呀!
那么我們怎么解決呢?
我們可以嘗試不在每個類中自己創(chuàng)建下級類,如果自己創(chuàng)建下級類就會出現(xiàn)當(dāng)下級類發(fā)生改變操作,自己也要跟著修改。
此時,我們只需要將原來由自己創(chuàng)建的下級類,改為傳遞的方式(也就是注入的方式),因為我們不需要在當(dāng)前類中創(chuàng)建下級類了,所以下級類即使發(fā)生變化(創(chuàng)建或減少參數(shù)),當(dāng)前類本身也無需修改任
何代碼,這樣就完成了程序的解耦。
是不是有點繞?沒關(guān)系,這樣想,原來我們是從下往上,一層包含一層,上面包含這下一層的New的對象,然后我們可以不這樣搞,我們可以從下往上走
也就是說,我們先創(chuàng)建好下層,然后把下層的屬性注入到上層,一層一層往上遞歸包含,最后到最頂上。
在傳統(tǒng)的代碼中對象創(chuàng)建順序是:Car -> Framework -> Bottom -> Tire改進(jìn)之后解耦的代碼的對象創(chuàng)建順序是:Tire -> Bottom -> Framework -> Car
通用程序的實現(xiàn)代碼,類的創(chuàng)建順序是反的,傳統(tǒng)代碼是 Car 控制并創(chuàng)建了
Framework,F(xiàn)ramework 創(chuàng)建并創(chuàng)建了 Bottom,依次往下,而用了容器之后是上級對象創(chuàng)建并控制下級對象了,而是下級對象把注入將當(dāng)前對象中,下級的控制權(quán)不再由上級類控制了,這樣即使下級類發(fā)生任何改變,當(dāng)前類都是不受影響的,這就是典型的控制反轉(zhuǎn),也就是 IoC 的實現(xiàn)思想
那么回到開頭,什么是loC?什么是DI?
1>理解loC
我們可以直接認(rèn)為 Spring 就是一個 IoC 容器。
既然它是一個容器,那么,容器主要的兩個核心功能,肯定是具有的
1、裝東西: 那些被 控制反轉(zhuǎn) 的對象(Bean),都可以存儲在 Spring 中。 2、取東西: 作為一個容器,不可能只存不取吧? 將 對象(Bean),從 Spring 中 取出來。
這也是 Spring IoC 容器 最核心的兩個功能【存 和 取 】。
那根據(jù)上面我的例子,為啥說能簡化開發(fā)呢?
將對象存放到容器中的好處:將對象存儲在 IoC 容器相當(dāng)于將以后可能用的所有工具制作好都放到倉庫中,需要的時候直接取就行了,用完再把它放回到倉庫。而 new 對象的方式相當(dāng)于,每次需要工具了,才現(xiàn)做,用完就扔掉了也不會保存,下次再用的時候還得重新做,這就是 IoC 容器和普通程序開發(fā)的區(qū)別。
2>理解DI
說到 IoC 不得不提的一個詞就是“DI”,DI 是 Dependency Injection 的縮寫,翻譯成中文是“依賴注入”的意思。
所謂依賴注入,就是由 IoC 容器在運行期間,動態(tài)地將某種依賴關(guān)系注入到對象之中。所以,依賴注入(DI)和控制反轉(zhuǎn)(IoC)是從不同的角度的描述的同一件事情,就是指通過引入 IoC 容器,利用依賴關(guān)系注入的方式,實現(xiàn)對象之間的解耦。
說一說DI和loC的區(qū)別
兩者其實是一個東西,但是是對一個事物從不同角度進(jìn)行了闡述。loC就是把某個對象交給Spring,然后用的時候跟他要,Spring怎么把對象給我我我不關(guān)心,我只要能拿到就可以了。而DI就是一個具體的實現(xiàn),DI關(guān)于于怎么將依賴注入對應(yīng)的對象里面。
哪一個例子來說
還是這個車,我們從兩個角度來說一下
處理思維(loC):一個類外部依賴的對象,其控制權(quán)限發(fā)生了反轉(zhuǎn),我們就不再去new它了,而是直接用。然后直接從Spring哪里拿,告訴他,我要用實際操作(DI):這里我們從底向上就不是new了,而是Spring中,把我的下一級拿過來,直接注入。
所以DI是實際實現(xiàn),但是loC是思想。
1>Spring 是什么?如何理解 Spring?
Spring 是一個包含 眾多工具方法 的 IoC 容器。既然 Spring 是一個 IoC 容器(反轉(zhuǎn)控制容器)。Spring是 存儲 IoC【反轉(zhuǎn)控制(后的對象)】 的一個容器
2>IoC 和 DI 是什么?有什么區(qū)別?
IoC – Inversion Of Control(控制反轉(zhuǎn))主要是將 對象的權(quán)限(創(chuàng)建與銷毀)交由 Spring 來管理。程序員 不必再去 new 對象了!在使用到某個對象的時候,直接向 Spring 索取,直接使用即可。DI dependency injection(依賴注入)將 引入的依賴 (執(zhí)行所依賴的對象),拿過來使用。區(qū)別:IoC 是一種 思想。DI 是具體的實現(xiàn)。
Spring核心功能?
這里上面也說了,這里最后再提一下
既然 Spring 是一個容器,那么,肯定是具有容器的兩個核心功能(存 和 取)。1、將 Bean(反轉(zhuǎn)的對象)存儲到 Spring 容器中。2、將 Bean(反轉(zhuǎn)的對象)從 Spring 容器中取出來。這也就是 Spring 的 兩個核心功能。
三丶Spring創(chuàng)建和使用
準(zhǔn)備環(huán)境
首先就是創(chuàng)建一個maven項目
然后之后直接創(chuàng)建就好
這里沒有太多可以說的,主要就是要記得添加一下spring的依賴
org.springframework spring-context 5.2.3.RELEASE org.springframework spring-beans 5.2.3.RELEASE
創(chuàng)建核心容器–注解配置方式
這里我們創(chuàng)建容器有多種方式,比如說
ApplicationContext context = new ClassPathXmlApplicationContext(“spring-config.xml”);
但是這里種方式用的很少,這里我也不在對他介紹過多,這里我介紹另外一種
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(“org.example.lifecycle”);
首先說一下這種方式
具體的格式為
Application context = new 接口實現(xiàn)類()
這里我們就會有很多很多的接口,但是這里我們就只介紹兩種
如果說你是加載類加載路徑下的xml容器,然后再把內(nèi)容裝到容器當(dāng)中,那么過程無疑就很麻煩,這里我們不推薦使用這種方式。我們推薦用配置的方式去創(chuàng)建容器
1>包掃描
可以看到,我上面的圖中,通過注解配置的方式去創(chuàng)建容器的時候,加了個包的路徑,什么意思呢?
但是這里有問題呀!我不可能這個類中所有的東西都是要使用的,那我怎么辦呢?
2>添加類注解–五類注解解析
這里的話就要加注解,告訴容器,那個類是我需要的,那個是我不需要的
1. 類注解:@Controller、@Service、@Repository、@Component、@Configuration。2. 方法注解:@Bean。
這里的話一一說明一下:
@Controller:表示的是業(yè)務(wù)邏輯層;用于web開發(fā)處理http請求和響應(yīng),類似servlet@Servie:服務(wù)層;做業(yè)務(wù)邏輯的@Repository:持久層;數(shù)據(jù)庫訪問,一般是數(shù)據(jù)庫操作@Component:一般組件@Configuration:配置層。系統(tǒng)啟動前提前加載一些資源
然后這里我們進(jìn)行寫個代碼驗證一下
那么誰可以被掃描注冊到容器中呢?答案毋庸置疑,肯定就是 UserService
這里特別說明一下?。。。。。。。。。。。。。。。。。。。。。。。?/p>
你類注解這里的ID是有講究的:
就是說:
Bean ID/名稱,默認(rèn)是類名首字母小寫
那么我接就接著往下說,你類當(dāng)中所有的東西都是需要的嘛?那肯定不一定呀,對不對?那么我們怎么辦呢?這個時候就要用到我們的方法注解了
3>添加方法注解
這里我們就直接上代碼圖
所以你甚至還可以再過分一點:在當(dāng)前方法注解的同時放開類注解,讓類一邊被掃描的時候方法也在被掃描(玩的挺花哈)
所以其實你可以發(fā)現(xiàn), Spring 存放的東西,其實是一個類似于 Map 的這樣子的結(jié)構(gòu),這里的鍵就是我們的 BeanID ,值呢就是我們的 Bean對象
總結(jié)
這里小小的總結(jié)一下
說一下ApplicationContexte和BeanFactory的區(qū)別
四丶Bean對象的使用
通過容器對象.getBean()獲取
這里就是我們上面的使用方式
所以這里不做過多闡述,主要是下面的這種,是我們主要的學(xué)習(xí)目標(biāo)
依賴注入:把一個Bean對象,注入到另一個Bean的屬性當(dāng)中
獲取 bean 對象也叫做對象裝配,是把對象取出來放到某個類中,有時候也叫對象注入。
對象裝配(對象注入)的實現(xiàn)方法以下 3 種:
接下來,我們分別來看具體的實現(xiàn)
byType類型匹配
屬性注入是使用 @Autowired 實現(xiàn)的,將 Service 類注入到 Controller 類中。
這種的就是屬性/setter方法上加 @Autowired ,這里我們直接來代碼演示
繼續(xù)往下走,如果說你再多來幾個呢?就是我再來一個 屬性:二號張三 還能往出拿嘛?當(dāng)然可以拿,這根本不沖突,不是嘛?
那么問題就來了,既然字符對象我可以往出拿,那么其他類的對象我是不是也可以存著,然后需要的時候往出拿呢?
那就試一試唄?
byName:通過Bean的id/名稱來匹配
但是你仔細(xì)看一看,有沒有發(fā)現(xiàn)這個打印出來的有點眼熟?沒錯,他就是我們第一個創(chuàng)建的UserService對象
所以這啥意思?你是通過變量名稱去獲取打印對象的???
不知道,也不好說,所以我們試一試好嘛?
這里如果說對我這個us1有疑問的,那么可以看我上面 [三丶Spring創(chuàng)建和使用 == >創(chuàng)建核心容器–注解配置方式 ==> 3>添加方法注解]這里。往下走:
然后我們之后打印一下
所以就是的了?那么規(guī)則是什么呢?如果說我此時來一個us3呢?我這個時候是沒有new us3呢呀?
然后此時解決一下我們上面的問題,這里你怎么搞?那么觸發(fā)一個問題
如果此時你的id/名稱不存在或者說不唯一。怎么綁定?
這里先梳理一下,先是檢查類型,發(fā)現(xiàn)好幾個相同類型,然后就去檢查id,然后你此時id不唯一或者id不存在怎么辦?那就要會報錯?。。?/p>
方式一:使用 @Qualifier(“XXX”)
直接加注解,里面指定唯一的對象
方式二: 使用@Resource(name=“XXX”)
說一下@Autowired 和 @Resource 的區(qū)別
1.出身不同:@Autowired 來自于 Spring,而 @Resource 來自于 JDK 的注解;2.使用時設(shè)置的參數(shù)不同:相比于 @Autowired 來說,@Resource 支持更多的參數(shù)設(shè)置,例如name 設(shè)置,根據(jù)名稱獲取 Bean,@Autowired 只有一個 value 屬性3.用法不同@Autowired 支持 屬性注入,構(gòu)造方法注入,Setter 注入@Resource 支持 屬性注入,Setter 注入