Idea工具中創建 SpringBoot工程及入門詳解
SpringBoot 項目創建
創建Module
基於IDEA創建項目Module,模塊名為04-springboot-start,組id和包名為com.cy,如圖所示:
填寫module信息,如圖所示:
選擇項目module版本,暫時不需要自己手動添加任何依賴,如圖所示:
填寫Module名稱,完成module創建,如圖所示
項目結構分析
項目Module創建好以後,其代碼結構分析,如圖所示:
SpringBoot 項目啟動分析
啟動入口
SpringBoot 工程中由SpringBootApplication註解描述的類為啟動入口類,例如:
package com.cy; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application {//Application.class public static void main(String[] args) {//Main Thread SpringApplication.run(Application.class, args); } }
啟動過程概要分析
SpringBoot工程啟動時其簡易初始化過程,如圖所示:
在啟動過程中底層做瞭哪些事情,大致描述如下:
1)基於配置加載類(通過ClassLoader將指定位置的類讀到內存->底層通過線程調用IO從磁盤讀取到內存)。
2)對類進行分析(創建字節碼對象-Class類型,通過反射獲取器配置信息)。
3)對於指定配置(例如由spring特定註解描述)的對象存儲其配置信息(借助BeanDefinition對象存儲)。
4)基於BeanDefinition對象中class的配置構建類的實例(Bean對象),並進行bean對象的管理(可能會存儲到bean池)。
SpringBoot 快速入門分析
業務描述
在項目Module中定義一個類,類名為DefaultCache,然後將此類對象交給Spring創建並管理。最後通過單元測試對類的實例進行分析。
API設計分析
基於業務描述,進行API及關系設計,如圖所示:
代碼編寫及運行
基於業務及API設計,進行代碼編寫,其過程如下:
第一步:定義DefaultCache類
package com.cy.pj.common.cache; import org.springframework.stereotype.Component; /** * @Component 註解描述的類,表示此類交給Spring框架管理。 */ @Component public class DefaultCache { }
第二步:定義DefaultCacheTests單元測試類
package com.cy.pj.common.cache; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @SpringBootTest public class DefaultCacheTests { /** * @Autowired 註解描述的屬性由spring框架按照一定規則為其註入值(賦值) * 賦值過程是怎樣的? * 1)依賴查找?(請問查找規則是什麼?) * 2)依賴註入?(需要借助什麼技術?) */ @Autowired private DefaultCache defaultCache; @Test void testDefaultCache(){ System.out.println(defaultCache.toString()); //FAQ? defaultCache變量引用的對象是由誰創建的,存儲 到瞭哪裡?bean pool } }
第三步:運行單元測試類進行應用分析
啟動運行單元測試方法,檢測其輸出結果,基於結果分析:
1)SpringBoot項目中Bean對象的構建。
2)SpringBoot項目中Bean對象的獲取。
運行過程中的BUG分析
Bean類型找不到,如圖所示:
空指針異常(NullPointerExcetpion-NPE),如圖所示:
啟動類找不到,如圖所示:
啟動類有多個,如圖所示:
NoSuchBeanDefinition異常,如圖所示:
單元測試類中的方法添加瞭參數,如圖所示:
SpringBoot 項目中的對象特性分析
準備工作
第一步:創建項目Module,例如名字為05-springboot-features,如圖所示:
第二步:添加業務類ObjectPool,代碼如下:
package com.cy.pj.common.pool; @Component public class ObjectPool{//假設此對象為一個對象池 public ObjectPool(){//假設運行項目啟動類,此構造方法執行瞭,說明此類對象構建瞭。 Systemd.out.println("ObjectPool()") } }
思考:一般池對象有什麼特點?
1)在JVM內存會開辟一塊相對比較大的空間。
2)在這塊空間中存儲一些對象(思考基於什麼存儲結構進行存儲-數組,鏈表,散列表)。
3)基於“享元模式”設計思想,實現內存中對象的可重用性。
第三步:定義單元測試,代碼如下:
package com.cy.pj.pool; import com.cy.pj.common.pool.ObjectPool; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest public class ObjectPoolTests { @Autowired private ObjectPool objectPool01; @Autowired private ObjectPool objectPool02; @Test void testObjectPool01(){ System.out.println(objectPool01==objectPool02); } }
延遲加載
現在思考一個問題,對於ObjectPool這個類,假如項目啟動以後,暫時不會用到這個池對象,是否有必要對其進行創建(默認是會創建的)?我們知道沒必要,因為占用內存。那如何在啟動時不創建此類對象呢?借助Spring框架提供的延遲加載特性進行實現。例如,我們可以在需要延遲加載的類上使用@Lazy註解進行描述,代碼如下:
package com.cy.pj.common.pool; @Lazy @Component public class ObjectPool{//假設此對象為一個對象池 public ObjectPool(){//假設運行項目啟動類,此構造方法執行瞭,說明此類對象構建瞭。 Systemd.out.println("ObjectPool()") } }
此時,我們再去運行運行啟動類,檢測ObjectPool對象是否創建瞭,假如沒有創建,說明延遲加載生效瞭。此時,我們總結一下,什麼對象適合使用延遲加載特性呢?大對象,稀少用(項目啟動以後,暫時用不到)的對象。
註意:延遲加載並不是延遲對類進行加載,而是在啟動時,暫時不創建類的實例。假如想看一下內存中的類是否被加載瞭,可以通過JVM參數進行檢測,參數為-XX:+TraceClassLoading。
對象作用域分析
在實際的項目中內存中的對象有一些可能要反復應用很多次,有一些可能用完以後再也不用瞭或者說應用次數很少瞭。對於經常要重復使用的對象我可考慮存儲到池中(例如交給spring框架進行管理),應用次數很少的對象那就沒必要放到池中瞭,用完以後讓它自己銷毀就可以瞭。在Spring項目工程中為瞭對這樣的對象進行設計和管理,提供瞭作用域特性的支持,具體應用:
package com.cy.pj.common.pool; @Scope("singleton") @Lazy @Component public class ObjectPool{//假設此對象為一個對象池 public ObjectPool(){//假設運行項目啟動類,此構造方法執行瞭,說明此類對象構建瞭。 Systemd.out.println("ObjectPool()") } }
其中,在上面的代碼中,我們使用瞭@Scope註解對類進行描述,用於指定類的實例作用域。不寫@Scope默認就是單例(singleton)作用域,這個作用域會配合延遲加載(@Lazy)特性使用,表示此類的實例在需要時可以創建一份並且將其存儲到spring的容器中(Bean池),需要的時候從池中取,以實現對象的可重用。假如一些對象應用次數非常少,可以考慮不放入池中,進而使用@Scope(“prototype”)作用域對類進行描述,讓此類的對象何時需要何時創建,用完以後,當此對象不可達瞭,則可以直接被GC系統銷毀。
對象生命周期方法
程序中的每個對象都有生命周期,對象創建,初始化,應用,銷毀的這個過程稱之為對象的生命周期。在對象創建以後要初始化,應用完成以後要銷毀時執行的一些方法,我們可以稱之為生命周期方法。但不見得每個對象都會定義生命周期方法。在實際項目中往往一些池對象通常會定義這樣的一些生命周期方法(例如連接池)。那這樣的方法在spring工程中如何進行標識呢?通常要借助@PostConstruct和@PreDestroy註解對特定方法進行描述,例如:
package com.cy.pj.common.pool; @Scope("singleton") @Lazy @Component public class ObjectPool{//假設此對象為一個對象池 public ObjectPool(){ Systemd.out.println("ObjectPool()") } @PostConstruct public void init(){ System.out.println("init()"); } @PreDestroy public void destory(){ System.out.println("destory()"); } }
其中:
1)@PostConstruct 註解描述的方法為生命周期初始化方法,在對象構建以後執行.
2)@PreDestroy 註解描述的方法為生命周期銷毀方法,此方法所在的對象,假如存儲到瞭spring容器,那這個對象在從spring容器移除之前會先執行這個生命周期銷毀方法(prototype作用域對象不執行此方法).
SpringBoot 項目中的依賴註入過程分析
在SpringBoot工程中,假如類與類之間存在著一定的依賴關系,Spring是如何進行依賴註入的呢,現在我們就通過一個案例做一個分析。
準備工作
第一步:創建一個項目module,如圖所示:
第二步:啟動運行項目,檢測是否能成功啟動
案例設計及分析
為瞭更好理解spring框架的底層註入機制,現在進行案例API設計,如圖所示:
在這個案例中單元測試類CacheTests中定義一個Cache接口類型的屬性,然後由Spring框架完成對cache類型屬性值的註入。
代碼編寫及測試分析
第一步:定義Cache接口,代碼如下:
package com.cy.pj.common.cache; public interface Cache { }
第二步:定義Cache接口實現類SoftCache,代碼如下:
package com.cy.pj.common.cache; @Component public class SoftCache implements Cache{ }
第三步:定義Cache接口實現類WeakCache,代碼如下:
package com.cy.pj.common.cache; @Component public class WeakCache implements Cache{ }
第四步:定義CacheTests單元測試類,代碼如下:
package com.cy.pj.common.cache; import org.junit.jupiter.api.Test; @SpringBootTest public class CacheTests { @Autowired @Qualifier("softCache") private Cache cache; @Test public void testCache() { System.out.println(cache); } }
其中,@Autowired由spring框架定義,用於描述類中屬性或相關方法(例如構造方法)。Spring框架在項目運行時假如發現由他管理的Bean對象中有使用@Autowired註解描述的屬性或方法,可以按照指定規則為屬性賦值(DI)。其基本規則是:首先要檢測容器中是否有與屬性或方法參數類型相匹配的對象,假如有並且隻有一個則直接註入。其次,假如檢測到有多個,還會按照@Autowired描述的屬性或方法參數名查找是否有名字匹配的對象,有則直接註入,沒有則拋出異常。最後,假如我們有明確要求,必須要註入類型為指定類型,名字為指定名字的對象還可以使用@Qualifier註解對其屬性或參數進行描述(此註解必須配合@Autowired註解使用)。
第五步:運行CacheTests檢測輸出結果,基於結果理解其註入規則。
編寫及測試過程中的BUG分析
依賴註入異常,如圖所示:
總結(Summary)
本小節為springboot技術入門章節,主要講述瞭SpringBoot工程下,spring中bean對象的編寫,特性以及依賴註入的規則,希望通過這一小節的講解,同學們能夠理解我們為什麼要將對象交給spring管理,spring管理對象有什麼優勢,我們在springboot工程中應該如何配置這些對象。
到此這篇關於Idea工具中創建 SpringBoot工程及入門分析詳解的文章就介紹到這瞭,更多相關idea創建 SpringBoot工程內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Spring框架學習之Spring @Autowired實現自動裝配的代碼
- spring中向一個單例bean中註入非單例bean的方法詳解
- Spring超詳細講解註解開發
- 一文搞懂Spring循環依賴的原理
- spring IOC控制反轉原理詳解