如今軟件市場已經造成必定的規模,系統架構的複雜度也愈來愈高(例若有單體架構,分佈式架構,微服務架構)。軟件的整個架構體系正在發生很大變化,在這種變化中,企業如今更注重技術的開箱即用,更注重技術在生態圈中的深度融合,更注重輕量級的運維。由此spring boot誕生。
說明:學技術必定要了解技術發展史,並對技術的發展有必定的前瞻性。java
打開maven中的setting.xml 文件,並對其以下選項進行配置。面試
配置maven本地庫 (從maven遠程服務器下載的資源存儲到的位置)spring
`<localRepository>${user.home}/.m5/repository</localRepository>`
配置maven私服(配置到mirrors標籤內部)。apache
<mirror> <id>aliyun</id> <name>aliyun for maven</name> <mirrorOf>\*</mirrorOf> <url>https://maven.aliyun.com/repository/public</url> </mirror>
<profile> <id>jdk-1.8</id> <activation> <activeByDefault>true</activeByDefault> <jdk>1.8</jdk> </activation> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.compilerVersion> 1.8 </maven.compiler.compilerVersion> </properties> </profile>
打開STS 集成開發工具,建立spring boot項目,其具體步驟以下:api
點擊finish以後,項目便開始從maven配置中指定的私服(例如阿里雲的maven服務器)去下載起步依賴(SpringBoot項目中默認指定了項目啓動時須要的一些jar包依賴),這個過程可能會比較耗時(網絡最好不要用手機網絡,會致使不少資源下載不下來),假如指定版本的springboot項目之前建立過,它會默認先從本地庫查找,假如本地庫沒有,則從遠程庫去下載。
項目建立成功之後,其包視圖(Package Explorer)結構,如圖所示:
其中,在上圖呈現的項目結構中,全部的類和配置文件都是建立好項目之後,由STS工具幫咱們自動建立的。(假如你是普通的maven項目,這些類還有配置文件須要咱們本身手動建立)springboot
找到項目的入口類(使用了@SpringBootApplication
註解描述),而後運行啓動類,檢測啓動過程,SpringBoot在啓動時,控制檯會出現如圖標識:
項目啓動時發生了什麼呢? 參考下圖:
SpringBoot 項目在啓動時,首先基於啓動入口類上的註解描述,進行自動配置並掃描指定包以及子包中的類進行加載,而後檢測類上是否有Spring框架中指定的註解描述(例如@Component
,@Controller
,@Service
等)。假若有,則將類交給Spring框架中的BeanFactory工廠接口的實現類對象,此工廠對象會基於反射建立Bean的實例,假如此Bean指定了生命週期方法,還會調用生命週期方法。當實例建立之後,Spring框架還會基於類的做用域描述,將實例存儲到不一樣做用域的容器中。以實現Bean對象的科學應用。服務器
業務實現:
基於SpringBoot腳手架(或者架子工),經過Spring框架進行Bean對象的管理實現。網絡
建立一個DefaultCache類,存儲到 src/main/java 目錄,而後交給Spring管理。架構
package com.cy.pj.common.cache; import org.springframework.stereotype.Component; /* *FAQ 在SpringBoot工程中如何將一個類的實例交給Spring建立和管理? *1)將類放在啓動類所在包或子包中 *2)將類使用Spring框架中指定註解進行描述,例如@Component */ @Component //註解起的做用就是做標記 public class DefaultCache { }
其中,@Component
是Spring中用於描述Bean類的一個註解。用於告訴Spring這個類的實例由Spring建立,當此對象由Spring建立和管理時,默認會將對象存儲到池(Bean池)中。框架
添加 springboot 測試類,進行bean的獲取及測試,要放在src/test/java目錄中:
package com.cy.pj.common.cache; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest //SpringBoot工程中的單元測試類須要使用此註解進行描述 public class DefaultCacheTest { /** @Autowired 告訴spring框架運行時爲此屬性注入一個值 */ @Autowired private DefaultCache defaultCache; @Test public void testCache(){ System.out.println("defaultCache="+defaultCache); } }
其中:@SpringBootTest
註解用於告訴spring框架,此測試類交給spring管理。@Autowired
註解描述屬性時,用於告訴spring框架要爲此屬性注入一個值
<br/><br/>
圖中描述了DefaultCacheTests類與DefaultCache類的關係,這兩個類經過指定註解(@SpringBootTest
,@Component
)進行了描述,其意圖是告訴Spring框架這個兩個類的實例的建立由Spring負責,而且由Spring框架基於@Autowired
註解的描述完成DefaultCacheTests實例中有關DefaultCache類型的值的注入 (DI)。
異常類型:NoSuchBeanDefini tionException
咱們在STS中按Ctrl+Shift+T
打開查找框
![]()
![]()
![]()
爲對象設置做用域,設置延遲加載,設置生命週期方法(瞭解)
在Spring框架中,Spring爲由它建立和管理對象,設計了一些特性 , 例如 做用域,延遲加載,生命週期方法等,基於這些特性實現對Bean 對象的管理。
package com.cy.pj.common.pool; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; /** * FAQ? * 1)假如將此類交給spring管理,請問spring什麼時候建立此對象? * -- spring容器在啓動的時候就會建立這種類型的實例 * 2)假如一個對象建立之後,存儲到內存,長時間不用會有什麼影響? * -- 佔用資源!! * 3)你知道Spring中,Bean對象的延遲加載特性嗎? * -- 延遲加載就是按需加載,須要時去加載這個對象,不須要時就不要加載 * 4)你知道什麼場景下這個對象適合延遲加載嗎? * -- 大對象, 稀少用 * 5)對象建立之後,應用結束要銷燬對象嗎? * --若是對象使用頻繁,每次用完都銷燬,每次再使用就要再建立,對內存影響大。 * 6)程序中的每一個對象都有生命週期(正確),不見得每一個對象都有生命週期方法。 */ //@Lazy(true) @Lazy //(延遲加載/懶加載)此註解用於告訴spring框架,它描述的類的實例,假如暫時用不到,就不要先建立 @Scope("singleton") //默認就是單例做用域(這個類的實例在一個spring容器中默認只有一份) //@Scope("prototype") 每次從spring容器獲取對象都會建立一個新的實例 @Component public class ObjectPool { /*構造方法*/ public ObjectPool() { System.out.println("ObjectPool()"); } /* @PostConstruct 註解描述的方法會在對象構建之後執行,用於執行一些初始化操做*/ @PostConstruct public void init() { System.out.println("ObjectPool.init()"); } /** * @PreDestroy 註解描述的方法會在 單例 對象銷燬以前執行, spring容器在銷燬以前會先將容器(Bean池)中的對象進行移除, **在移除對象時,假如對象中定義了生命週期銷燬方法,此時還會調用對象的生命週期銷燬方法 */ @PreDestroy public void close() { System.out.println("ObjectPool.close()"); } }
其中:
@Lazy
註解用於描述類,其目的是告訴Spring框架此類支持延遲加載,一般會配合單例做用域使用。@Scope
是Spring中用於定義Bean對象做用域的一個註解,其經常使用的值有 singleton(整個內存有一份Bean實例,此實例什麼時候建立與類的延遲加載特性配置有關,此實例建立之後,生命週期會由Spring框架管理),prototype(每次獲取都會建立新實例,此實例會在須要時建立 與lazy特性無關,這個實例建立之後,不會交給Spring管理,Spring能夠對其初始化,但不負責銷燬。)等..
@PostConstruct
註解用於表述Bean對象生命週期方法中的初始化方法,此方法會在對象的構造方法以後執行(是對象建立之後的初始化)。@PreDestroy
註解用於描述Bean對象生命週期方法中的銷燬方法,此方法會在對象銷燬以前執行(看成用域爲prototype時,此方法不會執行)。第五步:
經過測試類測試做用域,延遲加載,生命週期方法。
package com.cy.pj.common.cache; @SpringBootTest public class ObjectPoolTests { @Autowired private ObjectPool objectPool; @Test public void testObjectPool() { //??? } }
經過對上面小節的學習
能說說Spring框架管理Bean對象有什麼優點嗎?( 面試)
Spring 是一個資源整合框架(Framework),經過spring可將不少資源(本身寫的對象或第三方提供的對象,例如鏈接池等)整合在一塊兒,而後進行科學應用,以便更好的對外提供服務。如圖所示:
![]()
在圖中,Spring框架能夠爲由它管理的對象(Bean)提供懶加載策略(對象暫時用不到,則無需加載和實例化),做用域(例如singleton-頻繁用時能夠考慮內存中只有一份,prototype-使用次數少時能夠用時建立,不用時銷燬),生命週期方法(更好實現對象的初始化和資源銷燬),以實現對象對系統資源的有效使用。同時Spring框架還能夠基於用戶設計管理對象與對象的依賴關係,以下降對象與對象之間的直接耦合,提升程序的可維護性和可擴展性。
假如一個接口的實現類的對象有多個,而且這些對象都交給了spring管理,那麼另一個類,如今依賴於這個接口,spring怎麼注入?
package com.cy.pj.common.cache; public interface Cache { }
package com.cy.pj.common.cache; import org.springframework.stereotype.Component; @Component public class WeakCache implements Cache{ }
package com.cy.pj.common.cache; @Component public class SoftCache implements Cache{ … }
package com.cy.pj.common.cache; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest public class CacheTests { @Autowired @Qualifier("softCache") private Cache cache; @Test public void testCache() { System.out.println(cache); } }
思考:
- @Autowired註解應用規則?
- @Qualifier註解的做用是什麼?
@Autowired
由spring框架定義,用於描述類中屬性或相關方法(例如構造方法)。Spring框架在項目運行時假如發現由他管理的Bean對象中有使用@Autowired
註解描述的屬性或方法,能夠按照指定規則爲屬性賦值(DI)。其基本規則是:首先要檢測容器中是否有與屬性或方法參數類型相匹配的對象,假若有而且只有一個則直接注入。其次,假如檢測到有多個,還會按照@Autowired
描述的屬性或方法參數名查找是否有名字匹配的對象,有則直接注入,沒有則拋出異常。最後,假如咱們有明確要求,必需要注入類型爲指定類型,名字爲指定名字的對象還可使用@Qualifier
註解對其屬性或參數進行描述(此註解必須配合@Autowired
註解使用)。具體過程可參考上圖的設計進行自行嘗試和實踐。