Spring是什麼,談談你對Spring的理解。這是初級開發人員必然被問道的問題,如果你不懂Spring你就無法從事這一行業,此處僅限技術人員,公司的繼承人等其他個例不受此限制。那麼Spring是什麼呢,Spring遵循分層的結構思想什麼什麼實現了高內聚低耦合巴拉巴拉一大堆,咬文嚼字不是我的強項,直接開幹,讓你們看看Spring到底是什麼東西。
通過maven下載好Spring的jar包
我們在src下/main/resources下創建配置文件applicationContext.xml 並為其配置xsd約束
把上面這一對約束複製到applicationContext.xml 中然後ctrls+s保存,Spring框架到目前為止已經搭建完畢。配置文件中的根標籤是beans,所以配置一定要寫到beans裡面。到目前為止Sping框架就搭建完畢了。創建下面一個pojo看看spring都有哪些功能
Sping有一個功能就是幫我們創建pojo對象實例,下面我麼需要在applicationContext.xml中將pojo配置為bean,註冊到spring容器中。
bean的name可以隨便取,一會我們會用到,class就是pojo的完整類名。下面請看java代碼
我們通過ClassPathXmlApplicationContext類傳入applicationContext.xml配置文件的相對路徑,創建出spring的容器對象ApplicationContext,在通過容器對象中的方法獲取到Spring容器為我們創建的user對象,其實Spring兩個容器,除了ApplicationContext外還有一個BeanFactory ,那麼他們有什麼區別呢?BeanFactory :是在getBean的時候才會生成類的實例. applicationContext :在加載applicationContext.xml(容器啟動)時候就會創建. BeanFactory 是一種懶加載的方式,那麼當訪問的bean過多的時候伺服器壓力就變大了,所以beanFactory實際上是一種淘汰了的容器,而applicationContext更類似於一種緩存機制,所以它受眾更高,下面看一下列印結果
可以看到User的toString方法已經打出,補充一下以上代碼我並沒有運行在java的main線程裡面,而是使用的junit單元測試。我們在main方法外部隨意創建一個public的方法,在上部使用@Test註解即可運行,這樣能夠幫我們節省在main方法內通過對象調用方法的時間。
以上的就是Spring被外行廣為流傳的,傳說中的IOC的使用,什麼是IOC中文意思就是控制反轉,什麼意思?我們平時創建對象需要自己手動創建,現在對象都是通過spring容器ApplicationContext創建,這就是所謂的IOC控制反轉,如果有了解工廠設計模式的朋友會更容易理解,ApplicationContext此處就相當於一個工廠類。我之前講解MyBatis框架的SqlSession就是由SqlSesionFactory創建的。
接下來我們看一下spring另一個特性,DI依賴注入是什麼。上面Java代碼中的username,userage都是由我手動設置的,但是這樣實在太過於麻煩,於是Spring提供了為對象屬性注入的功能。下面回到剛才xml中的userBean部分
創建property字標籤,name為pojo中需要注入的變量名,value就是需要注入的值,
結果顯示已經注入成功了。那麼spring是否能夠完成我們自定義java對象的注入呢?
新建一個pojo類User2並在User中作為變量引入,
xml中新增一個bean user2,將User2對象交給spring創建,在User的Bean配置user2的引用,property的name還是變量名,這裡的value要換成ref,ref為要引用的對象的bean的name,下面我們看執行結果
它的原理是spring讀到xml中的值調用pojo內部的set方法完成注入的m所以這種方式必須要有set方法。除此之外我們還可以通過構造方法在創建對象的時候為屬性賦值,在xml中使用<constructor-arg></constructor-arg>標籤來實現,也很簡單照葫蘆畫瓢參照上面的配就行。
注意構造函數有幾個參數這裡就要傳入幾個參數,如果你只創建了一個三個參數的構造方法,那你傳2個參數就報錯,沒傳參也報錯,所以必須創建所有參數的構造方法才能讓程序穩定運行,這種注入方式讓人很有負擔。除了構造外,spring還支持p名稱空間注入和spel表達式注入,spel基於set方法和構造方法注入的,所以我們通過圖中的注入方式足矣,也是主流的注入方式。p和spel注入在這裡就不演示了,以上就是spring的DI依賴注入了,下面我們看看如給集合對象注入,
還是先創建一個pojo,然後我們在xml中為集合注入值
如圖所示,如果沒有指定泛型,那麼可以用value傳值,也可以用ref傳對象,可以不指定集合元素的類型,還是比較簡單,下面看看輸出結果
IOC需要DI的支持為什麼呢?因為沒有DI的注入Spring創造出的對象都是空值是無法使用的,所以說IOC和DI多數是同時出現人們眼前的。 下面補充一下Bean元素的屬性
scope是範圍的意思,在絕地求生中scope意為瞄準鏡,如果你的隊友是個老外你就和他說 i want this 4times scope他就明白了。在bean中scope表示bean對象的作用域,有兩個選項singlton,和prototype。什麼意思呢,singlton時spring只會創建單例對象,就是你反覆從容器中取到堆中的同一對象,而prototype則會創建多個對象。
那麼bean的生命周期是什麼呢,我認為通常生命周期這四個字只出現在web層面,所以這裡應該是配置controller的,看它的兩個屬性nit-method="init" 和destroy-method="destory",init是初始化的意思,裡面寫的是pojo的方法名,該方法一定是public的,而destory是銷毀方法,同init一樣用法,那麼他們分別是什麼時候執行的呢?如果使用applicationContext容易,那麼項目啟動時就會執行init方法,銷毀方法想要執行,需要是單例創建的Bean而且在工廠關閉的時候,Bean才會被銷毀. 什麼時候工廠開啟關閉呢?web項目中隨著中間件tommcat啟動,那麼bean的init就會被執行,關閉tommcat時 destory方法就會執行。
最後給大家看一道java面試題,問圖下輸出結果
有的人一看,main方法裡是空的,怎麼輸出啊?原來啊,在我們執行main方法之前,Jvm的classLoader需要將這個類加載到內存,首先加載的就是被static修飾的變量,也就是全局變量。這裡先聲明一個List 集合,然後在堆中創建一個ArrayList的子類對象,大家看這個對象的創建方法是不是與我們平時創建對象的方式是不是不太一樣呢?這個叫做匿名內部類,匿名內部類被創建時會執行它的方法,因為它的匿名內部類,所以和我們平時通過對象調用方法不太一樣,這裡沒有顯示調用它的對象名,但是方法還是被執行了。先對集合添加一個子串,然後列印集合中的內容,那麼列印出來的是什麼呢?結果是null,為什麼呢?因為在內部類的方法執行完成之前,還沒有結束對象的創建,所以聲明NAMES的引用並沒有與堆中任一對象進行連接,此處列印的相當於List<String> NAMES;只完成了前半段語句,所以列印出來的是空的,如果等內部類中方法都結束時,在main中重新列印NAMES的內容才可以看到集合中的元素。這道題主要考察的是Java實例化一個對象在堆棧中的過程。
以上就是今天的內容了,Spring中有著非常多的設計模式的影子,並不想SpringMVC 或MyBatis中有比較深的東西,所以我們只需要會使用spring框架就夠了。