03-基於IDEA建立SpringBoot項目並進行入門分析

SpringBoot 項目建立

建立Module

基於IDEA建立項目Module,模塊名爲04-springboot-start,組id和包名爲com.cy,如圖所示:
image.png
填寫module信息,如圖所示:
image.png
選擇項目module版本,暫時不須要本身手動添加任何依賴,如圖所示:
image.png
填寫Module名稱,完成module建立,如圖所示
image.pngspring

項目結構分析

項目Module建立好之後,其代碼結構分析,如圖所示:api

image.png

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工程啓動時其簡易初始化過程,如圖所示:springboot

image.png

在啓動過程當中底層作了哪些事情,大體描述以下:
1)基於配置加載類(經過ClassLoader將指定位置的類讀到內存->底層經過線程調用IO從磁盤讀取到內存)。
2)對類進行分析(建立字節碼對象-Class類型,經過反射獲取器配置信息)。
3)對於指定配置(例如由spring特定註解描述)的對象存儲其配置信息(藉助BeanDefinition對象存儲)。
4)基於BeanDefinition對象中class的配置構建類的實例(Bean對象),從進行bean對象的管理。框架

SpringBoot 快速入門分析

業務描述

在項目Module中定義一個類,類名爲DefaultCache,而後將此類對象交給Spring建立並管理。最後經過單元測試對類的實例進行分析。單元測試

API設計分析

基於業務描述,進行API及關係設計,如圖所示:測試

image.png

代碼編寫及運行

基於業務及API設計,進行代碼編寫,其過程以下:spa

第一步:定義DefaultCache類prototype

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;
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類型找不到,如圖所示:

image.png

  • 空指針異常(NullPointerExcetpion-NPE),如圖所示:

image.png

SpringBoot 項目中的對象特性分析

準備工做

第一步:建立項目Module,例如名字爲05-springboot-features,如圖所示:
image.png

第二步:添加業務類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,如圖所示:
image.png
第二步:啓動運行項目,檢測是否能成功啓動

案例設計及分析

爲了更好理解spring框架的底層注入機制,如今進行案例API設計,如圖所示:

image.png

在這個案例中單元測試類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分析

  • 依賴注入異常,如圖所示:

image.png

總結(Summary)

本小節爲springboot技術入門章節,主要講述了SpringBoot工程下,spring中bean對象的編寫,特性以及依賴注入的規則,但願經過這一小節的講解,同窗們可以理解咱們爲何要將對象交給spring管理,spring管理對象有什麼優點,咱們在springboot工程中應該如何配置這些對象。

相關文章
相關標籤/搜索